﻿#include "TeamManager.h"
#include "CenterService.h"
#include "Cache/OfflineCharacterDataMgr.h"
#include "Cache/OfflineCharacterData.h"
#include "Active/ActiveCharacter.h"
#include "Active/ActiveCharacterMgr.h"
#include "Common/Utility/ServerTime.h"
#include "Common/TableDataEx/TeamCfg.h"
#include "Common/TableData/TeamTeamCfg.h"
#include "ChatCenter/ChatCenter.h"
#include "RelationMgr/RelationMgr.h"
#include "Room/RoomMgr.h"
#include "ActivityMgr/ActivityMgr.h"
#include "Common/ActivityDefine.h"
#include "Common/TableData/ConstantConstantCfg.h"
#include "Common/TableData/MapMapCfg.h"
#include "Common/TableDataEx/MapCfg.h"

TeamManager::TeamManager()
{
	_teamPool = new ObjectPool < Team >;
	_teamIdMap.clear();
	_teamList.clear();
	_freeTeamList.clear();
	_sceneTeamList.clear();
	_teamTypeIdMap.clear();
	_autoMatchCharacterMap.clear();
	_autoMatchTeamIdMap.clear();
	_team_id = 1;
	_const_jail_id = 0;
}

TeamManager::~TeamManager()
{
}

bool TeamManager::Init()
{
	IMessageDispatch *pMessageDispatch = g_GetCenterService()->GetServiceMessageDispatch();
	if (nullptr == pMessageDispatch)
	{
		MMOLOG_FMT_ERROR("[center] TeamManager::Init....nullptr == pMessageDispatch ");
		return false;
	}
	
	pMessageDispatch->registerClientHandler(EMODULE_ID_TEAM, this);
	pMessageDispatch->registerServerHandler(EMODULE_ID_TEAM, this);

	g_GetActiveCharacterMgr()->AddCharacterObserver(this);

	//流放之地地图
	const ConstantConstantCfgInfo *pJailMapID = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_ClearPoint_Jail);
	if (nullptr == pJailMapID)
	{
		MMOLOG_FMT_ERROR("[center] TeamManager::Init.....nullptr == pJailMapID, id:%d ", EArg_ClearPoint_Jail);
		return false;
	}
	_const_jail_id = pJailMapID->constantdata;

	return true;
}

bool TeamManager::UnInit()
{
	IMessageDispatch *pMessageDispatch = g_GetCenterService()->GetServiceMessageDispatch();
	if (nullptr != pMessageDispatch)
	{
		pMessageDispatch->unregisterClientHandler(EMODULE_ID_TEAM);
		pMessageDispatch->unregisterServerHandler(EMODULE_ID_TEAM);
	}

	_teamIdMap.clear();

	for (TeamList::iterator iter = _teamList.begin(); iter != _teamList.end(); ++iter)
	{
		if (nullptr != iter->second)
		{
			_teamPool->FreeObj(iter->second);
			iter->second = nullptr;
		}
	}
	_teamList.clear();

	for (FreeTeamList::iterator iter = _freeTeamList.begin(); iter != _freeTeamList.end(); ++iter)
	{
		if (nullptr != *iter)
		{
			_teamPool->FreeObj(*iter);
		}
	}
	_freeTeamList.clear();

	_sceneTeamList.clear();
	_teamTypeIdMap.clear();
	_autoMatchCharacterMap.clear();
	_autoMatchTeamIdMap.clear();

	g_GetActiveCharacterMgr()->RemoveCharacterObserver(this);

	MMO_DELETE(_teamPool);



	return true;
}

void TeamManager::onCharacterLogin(ActiveCharacter *pOnlineCharacter)
{
	if (nullptr == pOnlineCharacter)	return;

	OnLogin(pOnlineCharacter);
	//将我的血量同步给其他队员
	//OnHpUpdate(pOnlineCharacter);

	LoginSync(pOnlineCharacter);
}

void TeamManager::onCharacterLogout(ActiveCharacter *pOnlineCharacter)
{
	if (nullptr == pOnlineCharacter)	return;
	OnLogoff(pOnlineCharacter);
}

void TeamManager::onCharacterUpdate(ActiveCharacter *pOnlineCharacter)
{
	if (nullptr == pOnlineCharacter)	return;
	OnHpUpdate(pOnlineCharacter);
}

void TeamManager::onCharacterDel(OfflineCharacterData *pOffLineCharacter)
{
	if (nullptr == pOffLineCharacter)	return;
	OnDeleteCharacter(pOffLineCharacter);
}

void TeamManager::onCharacterSwitchScene(ActiveCharacter *pOffLineCharacter)
{
	if (nullptr == pOffLineCharacter)	
		return;

	CharIDType charId = pOffLineCharacter->GetCharID();
	ActiveCharacter* pOnlineCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnlineCharacter)
		return;

	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
		return;

	//进入流放之地 退出队伍
	uint32_t mapId = pOffLineCharacter->GetMapID();
	if (_const_jail_id == mapId)
	{
		QuitTeam(charId);
		return;
	}

	//进入副本 解除跟随
	const MapMapCfgInfo*  pMapCfg = g_GetMapMapCfgTable()->GetMapMapCfgInfo(mapId);
	if (nullptr != pMapCfg && pMapCfg->mapType == DYNAMIC_MAP && !g_GetMapCfgMgr()->IsUnionDunGeonMap(mapId) && !g_GetMapCfgMgr()->IsUnionHomeMap(mapId))
	{
		myTeam->CancelAllFollow();
		ProtoBuf::WCCancelFollowNotify cancelFollowNotify;
		cancelFollowNotify.set_leaderid(charId);
		BroadcastTeam(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_CANCEL_FOLLOW_NOTIFY, &cancelFollowNotify);
	}

	//更新队伍场景信息
	if (myTeam->IsMember(charId))
	{
		TeamMember* member = myTeam->GetMember(charId);
		if (nullptr == member)	return;
		member->sceneId = pOnlineCharacter->GetSceneID();
		if (myTeam->IsLeader(charId))
		{
			RemoveFromScene(myTeam->SceneID(), myTeam->TeamID());
			AddToScene(member->sceneId, myTeam->TeamID());
			myTeam->SetSceneID(member->sceneId);
		}
	}
}

void TeamManager::onCharacterDisconnect(ActiveCharacter *pOffLineCharacter)
{
	if (nullptr == pOffLineCharacter)	return;
	OnLogoff(pOffLineCharacter);
}

void TeamManager::onCharacterReconnect(ActiveCharacter *pOffLineCharacter)
{
	if (nullptr == pOffLineCharacter)	return;
	OnLogin(pOffLineCharacter);
}

void TeamManager::LoginSync(ActiveCharacter *pOnlineCharacter)
{
	if (nullptr == pOnlineCharacter)	return;

	CharIDType charId = pOnlineCharacter->GetCharID();
	OfflineCharacterData *pOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOfflineCharacterData)		
		return;

	Team* myTeam = FindTeam(charId);
	if (nullptr != myTeam && myTeam->IsMember(charId))
	{
		if (myTeam->IsLeader(charId))
		{
			myTeam->CancelAllFollow();
		}
		else
		{
			myTeam->SetFollow(charId, false);
		}

		WCMemberAttrUpdateToMeNotify notifys;
		WCMemberHpUpdateNotify* notify = notifys.add_notifys();
		notify->set_memberid(charId);

		Attr* attr = notify->add_attrchange();
		attr->set_attrnum(P_HP);
		attr->set_attrvalue(pOfflineCharacterData->GetHp());

		attr = notify->add_attrchange();
		attr->set_attrnum(P_MAX_HP);
		attr->set_attrvalue(pOfflineCharacterData->GetMaxHp());

		attr = notify->add_attrchange();
		attr->set_attrnum(P_LEVEL);
		attr->set_attrvalue(pOfflineCharacterData->GetLevel());

		BroadcastTeam(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_OTHERMEMBERHPUPDATETOMENOTIFY, &notifys);
	}
}

void TeamManager::LoginSyncOhter(CharIDType charId)
{
	ActiveCharacter* pOnlineCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pOnlineCharacter)
		return;

	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
		return;

	SET_UINT64 playerList;
	myTeam->GetMemeberList(playerList);
	WCMemberAttrUpdateToMeNotify notifys;
	SET_UINT64::iterator iter = playerList.begin();
	for (; iter != playerList.end(); iter++)
	{
		if (charId == *iter)
			continue;

		ActiveCharacter* pOtherActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(*iter);
		if (nullptr == pOtherActiveCharacter)
			continue;

		OfflineCharacterData *pOtherOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(*iter);
		if (nullptr == pOtherOfflineCharacterData)
			return;

		WCMemberHpUpdateNotify* notify = notifys.add_notifys();
		notify->set_memberid(*iter);
		Attr* attr = notify->add_attrchange();
		attr->set_attrnum(P_HP);
		attr->set_attrvalue(pOtherOfflineCharacterData->GetHp());

		attr = notify->add_attrchange();
		attr->set_attrnum(P_MAX_HP);
		attr->set_attrvalue(pOtherOfflineCharacterData->GetMaxHp());
		
		attr = notify->add_attrchange();
		attr->set_attrnum(P_LEVEL);
		attr->set_attrvalue(pOtherOfflineCharacterData->GetLevel());
	}

	if (playerList.size() - 1 > 0)
	{
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_OTHERMEMBERHPUPDATETOMENOTIFY, &notifys);
	}
}

void TeamManager::onClientMessage(uint32_t actionId, RECV_PACKAGE& package, uint64_t Id /* = 0 */)
{
	switch (actionId)
	{
	case CLIENT_TO_CENTER_CREATE_TEAM:
	{
		HandleCreateTeam(Id, package);
		break;
	}
	case CLIENT_TO_CENTER_QUERY_TEAMINFO:
	{
		HandleQueryTeam(Id, package);
		break;
	}
	case CLIENT_TO_CENTER_OTHER_TEAM:
	{
		HandleQueryOtherTeam(Id, package);
		break;
	}
	case CLIENT_TO_CENTER_APPLY_JOIN:
	{
		HandleApplyJoinReq(Id, package);
		break;
	}
	case CLIENT_TO_CENTER_JOIN_TEAM_ECHO:
	{
		HandleJoinTeamEchoReq(Id, package);
		break;
	}
	case CLIENT_TO_CENTER_QUIT_TEAM:
	{
		HandleQuitTeamReq(Id, package);
		break;
	}
	case CLIENT_TO_CENTER_INVITE_JOIN:
	{
		HandleInviteJoin(Id, package);
		break;
	}
	case CLIENT_TO_CENTER_INIVATE_JOIN_ECHO:
	{
		HandleInviteJoinEchoReq(Id, package);
		break;
	}
	case CLIENT_TO_CENTER_DELETE_MEMBER:
	{
		HandleDeleteMember(Id, package);
		break;
	}
	case CLIENT_TO_CENTER_TRANSFER_TEAM:
	{
		HandleTransferTeam(Id, package);
		break;
	}
	case CLIENT_TO_CENTER_TEAM_SETTING:
	{
		HandleTeamSetting(Id, package);
		break;
	}
	case CLIENT_TO_CENTER_AUTO_MATCH:
	{
		HandleAutoMatchReq(Id, package);
		break;
	}
	case CLIENT_TO_CENTER_APPLY_LIST:
	{
		HandleApplyListReq(Id, package);
		break;
	}
	case CLIENT_TO_CENTER_CLEAR_APPLY_LIST:
	{
		HandleClearApplyListReq(Id, package);
		break;
	}
	case CLIENT_TO_CENTER_TEAM_FOLLOW:
	{
		HandleTeamFollowReq(Id, package);
		break;
	}
	case CLIENT_TO_CENTER_LEADER_POS_INFO:
	{
		HandleLeaderPosInfoReq(Id, package);
		break;
	}
	case CLIENT_TO_CENTER_TEAM_ENSURE_FOLLOW:
	{
		HandleTeamEnsureFollowReq(Id, package);
		break;
	}
	case CLIENT_TO_CENTER_CANCEL_FOLLOW:
	{
		HandleTeamCancelFollowReq(Id, package);
		break;
	}
	case CLIENT_TO_LOGIC_STAR_SOUL_RESP:
	{
		HandleStarSoulReponse(Id, package);
		break;
	}
	default:
		break;
	}
}

void TeamManager::onServerMessage(uint32_t actionId, RECV_PACKAGE &package)
{
	switch (actionId)
	{
	case LOGIC_TO_CENTER_LEADER_POS_INFO:
	{
		OnLeaderPosInfoReq(package);
		break;
	}
	case LOGIC_TO_CENTER_LEADER_POS_INFO_ERROR:
	{
		OnLeaderPosInfoErrorReq(package);
		break;
	}
	case LOGIC_TO_CENTER_CALL_TEAM_MEMBERS:
	{
		OnCallTeamMembersReq(package);
		break;
	}
	case LOGIC_TO_CENTER_TEAM_ADD_CLOSENESS:
	{
		OnTeamAddClosenessReq(package);
		break;
	}
	case LOGIC_TO_CENTER_CANCEL_FOLLOW:
	{
		OnMemberCancelFollow(package);
		break;
	}
	default:
		break;
	}
}

bool TeamManager::OnLeaderPosInfoReq(RECV_PACKAGE &package)
{
	ProtoBuf::GWLeaderPosInfoRsp leaderPosInfoRsp;
	ProtoBuf::WCLeaderPosInfoRsp clientRsp;

	if (!leaderPosInfoRsp.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[logic] TeamManager::HandleLeaderPosInfoReq GWLeaderPosInfoRsp parse failed...");
		return false;
	}

	CharIDType charId = leaderPosInfoRsp.charid();
	CharIDType leaderId = leaderPosInfoRsp.leaderid();

	Team* myTeam = FindTeam(leaderId);
	if (nullptr == myTeam)
	{
		clientRsp.set_ret(RET_TEAM_NO_EXIST);
		g_GetCenterService()->SendDataToClient(leaderId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_LEADER_POS_INFO, &clientRsp);
		return false;
	}

	if (nullptr != myTeam && !myTeam->IsMember(leaderId))
	{
		clientRsp.set_ret(RET_TEAM_NO_EXIST);
		g_GetCenterService()->SendDataToClient(leaderId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_LEADER_POS_INFO, &clientRsp);
		return false;
	}

	//判断队长是否发生变化了
	if (leaderId != myTeam->Leader())
	{
		clientRsp.set_ret(RET_FAIL);
		g_GetCenterService()->SendDataToClient(leaderId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_LEADER_POS_INFO, &clientRsp);
		return false;
	}

	if (charId > 0)
	{
		//队长已经下线了
		ActiveCharacter* pLeaderActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(leaderId);
		if (nullptr == pLeaderActiveCharacter)
		{
			clientRsp.set_ret(RET_TEAM_LEADER_NO_ONLINE);
			g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_LEADER_POS_INFO, &clientRsp);
			return false;
		}

		ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
		if (nullptr == pActiveCharacter)
		{
			return false;
		}

		//判断自己是否是队长
		if (myTeam->IsLeader(charId))
		{
			clientRsp.set_ret(RET_FAIL);
			g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_LEADER_POS_INFO, &clientRsp);
			return false;
		}

		if (pActiveCharacter->GetLifeStatus() == State_dead)
		{
			clientRsp.set_ret(RET_FAIL);
			g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_LEADER_POS_INFO, &clientRsp);
			return false;
		}

		if (myTeam->GetMemberOnline(charId) == false)
		{
			clientRsp.set_ret(RET_FAIL);
			g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_LEADER_POS_INFO, &clientRsp);
			return false;
		}

		//通知客户端队长位置坐标
		clientRsp.set_ret(RET_SUCCESS);
		clientRsp.set_sceneid(leaderPosInfoRsp.sceneid());
		clientRsp.mutable_dstpos()->CopyFrom(leaderPosInfoRsp.dstpos());

		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_LEADER_POS_INFO, &clientRsp);
	}
	else
	{
		ActiveCharacter* pLeaderActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(leaderId);
		if (nullptr == pLeaderActiveCharacter)
		{
			return false;
		}

		SET_UINT64 playerList;
		myTeam->GetMemeberList(playerList);
		for (SET_UINT64::iterator iter = playerList.begin(); iter != playerList.end(); ++iter)
		{
			if (*iter == leaderId)
			{
				continue;
			}

			ActiveCharacter *pPlayerActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(*iter);
			if (nullptr == pPlayerActiveCharacter)
			{
				continue;
			}

			//只给同一个场景的队员设置跟随状态
			if (myTeam->SceneID() != pPlayerActiveCharacter->GetSceneID())
			{
				continue;
			}

			if (pPlayerActiveCharacter->GetLifeStatus() == State_dead)
			{
				continue;
			}

			//通知客户端队长位置坐标
			clientRsp.set_ret(RET_SUCCESS);
			clientRsp.set_sceneid(leaderPosInfoRsp.sceneid());
			clientRsp.mutable_dstpos()->CopyFrom(leaderPosInfoRsp.dstpos());

			g_GetCenterService()->SendDataToClient(*iter, EMODULE_ID_TEAM, CENTER_TO_CLIENT_LEADER_POS_INFO, &clientRsp);
		}
	}
	
	return true;
}

bool TeamManager::OnLeaderPosInfoErrorReq(RECV_PACKAGE &package)
{
	ProtoBuf::GWLeaderPosInfoError errorNotify;
	ProtoBuf::WCLeaderPosInfoRsp clientRsp;

	if (!errorNotify.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("[logic] TeamManager::OnLeaderPosInfoErrorReq GWLeaderPosInfoError parse failed...");
		return false;
	}

	CharIDType leaderId = errorNotify.leaderid();
	CharIDType charId = errorNotify.charid();

	Team* myTeam = FindTeam(leaderId);
	if (nullptr == myTeam)
	{
		clientRsp.set_ret(RET_TEAM_NO_EXIST);
		g_GetCenterService()->SendDataToClient(leaderId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_LEADER_POS_INFO, &clientRsp);
		return false;
	}

	if (nullptr != myTeam && !myTeam->IsMember(leaderId))
	{
		clientRsp.set_ret(RET_TEAM_NO_EXIST);
		g_GetCenterService()->SendDataToClient(leaderId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_LEADER_POS_INFO, &clientRsp);
		return false;
	}

	//队长已经下线了
	ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(leaderId);
	if (nullptr == pActiveCharacter)
	{
		return false;
	}

	//再拉取一次队长位置坐标
	ProtoBuf::WGLeaderPosInfoReq logicReq;
	logicReq.set_leaderid(leaderId);
	logicReq.set_charid(charId);
	g_GetCenterService()->SendDataToLogicByCharID(leaderId, EMODULE_ID_TEAM, CENTER_TO_LOGIC_LEADER_POS_INFO, &logicReq);

	return true;
}

bool TeamManager::OnCallTeamMembersReq(RECV_PACKAGE &package)
{
	ProtoBuf::GWTeamCallMembers callMembersReq;
	ProtoBuf::WCCallMembers notify;

	if (!callMembersReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("callMembersReq parse failed...");
		return false;
	}

	CharIDType leaderId = callMembersReq.leaderid();
	ProtoBuf::WGTeamCallMembers callMembers;
	callMembers.set_leaderid(leaderId);
	callMembers.set_itemidx(callMembersReq.itemidx());

	Team* myTeam = FindTeam(leaderId);
	if (nullptr == myTeam)
	{
		callMembers.set_ret(RET_TEAM_NO_EXIST);
		return g_GetCenterService()->SendDataToLogicByCharID(leaderId, EMODULE_ID_TEAM, CENTER_TO_LOGIC_CALL_TEAM_MEMBERS, &callMembers);
	}

	if (!myTeam->IsLeader(leaderId))
	{
		callMembers.set_ret(RET_DUPLICATE_NOT_TEM_LEADER);
		return g_GetCenterService()->SendDataToLogicByCharID(leaderId, EMODULE_ID_TEAM, CENTER_TO_LOGIC_CALL_TEAM_MEMBERS, &callMembers);
	}

	if (myTeam->MemberCount() <= 1 || myTeam->IsAllMemeberOfflineExceptLeader())
	{
		callMembers.set_ret(RET_PACKAGE_NO_MEM_CAN_BECALLED);
		return g_GetCenterService()->SendDataToLogicByCharID(leaderId, EMODULE_ID_TEAM, CENTER_TO_LOGIC_CALL_TEAM_MEMBERS, &callMembers);
	}

	notify.set_leader_id(leaderId);
	notify.set_mapid(callMembersReq.mapid());
	notify.mutable_pos()->CopyFrom(callMembersReq.pos());
	SET_UINT64 playerList;
	myTeam->GetMemeberList(playerList);
	playerList.erase(leaderId);

	StarSoulNotify tNotify;
	for (SET_UINT64::iterator iter = playerList.begin(); iter != playerList.end();)
	{
		ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(*iter);
		if (nullptr != pActiveCharacter && pActiveCharacter->GetMapID() == _const_jail_id)
		{
			tNotify.set_map_id(_const_jail_id);
			playerList.erase(iter++);
			continue;
		}
		if (g_GetActivityMgr()->InSonOfKillingStatus(*iter))
		{
			tNotify.set_item_id(ACTIVITY_SON_OF_KILLING_ITEM_ID);
			playerList.erase(iter++);
			continue;
		}
		++iter;
	}
	g_GetCenterService()->SendDataToClient(leaderId, EMODULE_ID_TEAM, SERVER_TO_CLIENT_STAR_SOUL_NOTIFY, &tNotify);

	if (playerList.size() > 0)
	{
		g_GetCenterService()->SendDataToClient(playerList, EMODULE_ID_TEAM, CENTER_TO_CLIENT_CALL_MEMBES, &notify);
	}

	callMembers.set_ret(RET_SUCCESS);
	return g_GetCenterService()->SendDataToLogicByCharID(leaderId, EMODULE_ID_TEAM, CENTER_TO_LOGIC_CALL_TEAM_MEMBERS, &callMembers);
}

bool TeamManager::OnTeamAddClosenessReq(RECV_PACKAGE &package)
{
	ProtoBuf::GWTeamAddCloseness notify;

	if (!notify.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("GWTeamAddCloseness parse failed...");
		return false;
	}

	CharIDType charId = notify.charid();
	uint32_t type = notify.type();
	AddTeamCloseness(charId, type);

	return true;
}

bool TeamManager::OnMemberCancelFollow(RECV_PACKAGE &package)
{
	ProtoBuf::GWMemberCancelFollow cancelFollow;
	if (!cancelFollow.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("GWMemberCancelFollow parse failed...");
		return false;
	}

	TeamID_t teamId = cancelFollow.teamid();
	Team* myTeam = FindTeamById(teamId);
	if (nullptr == myTeam)
	{
		return false;
	}

	for (int32_t i = 0; i != cancelFollow.charid_lst().size(); ++i)
	{
		CharIDType charId = cancelFollow.charid_lst(i);

		ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
		if (nullptr == pActiveCharacter)
			continue;
		
		if (!myTeam->IsMember(charId))
			continue;

		if (myTeam->IsLeader(charId))
			continue;

		if (pActiveCharacter->GetLifeStatus() == State_dead)
			continue;

		myTeam->SetFollow(charId, false);

		WCTeamEnsureFollowNotify ensureFollowNotify;
		ensureFollowNotify.set_charid(charId);
		ensureFollowNotify.set_isfollow(false);
		//通知非跟随状态的成员
		BroadcastTeam(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_ENSURE_FOLLOW_NOTIFY, &ensureFollowNotify, false, false);
	}
	return true;
}

bool TeamManager::HandleCreateTeam(CharIDType charId, RECV_PACKAGE &package)
{
	ProtoBuf::CWCreateTeamReq createTeamReq;
	ProtoBuf::WCCreateTeamRsp createTeamRsp;

	if (!createTeamReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWCreateTeamReq parse failed...");
		return false;
	}

	ProtoBuf::ERetCode ret = CreateTeam(charId);
	createTeamRsp.set_ret(ret);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_CREATE_TEAM, &createTeamRsp);

	return true;
}

bool TeamManager::HandleQueryTeam(CharIDType charId, RECV_PACKAGE &package)
{
	ProtoBuf::CWQueryTeamInfoReq queryTeamInfoReq;
	ProtoBuf::CWQueryTeamInfoRsp queryTeamInfoRsp;

	if (!queryTeamInfoReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWQueryTeamInfoReq parse failed...");
		return false;
	}

	ProtoBuf::ERetCode ret = QueryTeam(charId);
	queryTeamInfoRsp.set_ret(ret);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_QUERY_TEAM_INFO, &queryTeamInfoRsp);

	LoginSyncOhter(charId);
	//将其他队员的血量同步给我
	//OnOtherHpUpdate(charId);

	//将其他对应的在线状态同步给我
	return true;
}

bool TeamManager::HandleQueryOtherTeam(CharIDType charId, RECV_PACKAGE &package)
{
	ProtoBuf::CWQueryOtherTeamReq queryOtherTeamInfoReq;

	if (!queryOtherTeamInfoReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWQueryOtherTeamReq parse failed...");
		return false;
	}

	uint32_t type = queryOtherTeamInfoReq.type();
	uint32_t subType = queryOtherTeamInfoReq.subtype();

	QueryOtherTeam(charId, type, subType);

	return true;
}

bool TeamManager::HandleApplyJoinReq(CharIDType charId, RECV_PACKAGE& package)
{
	ProtoBuf::CWApplyJoinReq applyJoinReq;
	ProtoBuf::WCApplyJoinRsp applyJoinRsp;

	if (!applyJoinReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWApplyJoinReq parse failed...");
		return false;
	}

	CharIDType dstId = applyJoinReq.playerid();
	ProtoBuf::ERetCode ret = JoinTeam(charId, dstId);
	applyJoinRsp.set_ret(ret);

	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_APPLY_JOIN, &applyJoinRsp);

	return true;
}

bool TeamManager::HandleJoinTeamEchoReq(CharIDType charId, RECV_PACKAGE& package)
{
	ProtoBuf::CWJoinTeamEchoReq joinTeamEchoReq;
	ProtoBuf::CWJoinTeamEchoRsp	joinTeamEchoRsp;

	if (!joinTeamEchoReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWJoinTeamEchoReq parse failed...");
		return false;
	}

	std::vector<CharIDType> agreeList;
	std::vector<CharIDType> disagreeList;

	for (int32_t i = 0; i < joinTeamEchoReq.agreelist_size(); i++)
	{
		CharIDType dstId = joinTeamEchoReq.agreelist(i);
		if (dstId != 0)
		{
			agreeList.push_back(dstId);
		}
	}

	for (int32_t i = 0; i < joinTeamEchoReq.disagreelist_size(); i++)
	{
		CharIDType dstId = joinTeamEchoReq.disagreelist(i);
		if (dstId != 0)
		{
			disagreeList.push_back(dstId);
		}
	}

	ProtoBuf::ERetCode ret = JoinTeamEcho(charId, agreeList);
	joinTeamEchoRsp.set_ret(ret);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_JOIN_TEAM_ECHO, &joinTeamEchoRsp);

	//给拒绝加入的玩家发送通知
	DisagreeTeamEcho(charId, disagreeList);
	//通知拒绝加入的玩家
	SendJoinTeamEchoNotify(charId, disagreeList);

	return true;
}

bool TeamManager::HandleQuitTeamReq(CharIDType charId, RECV_PACKAGE& package)
{
	ProtoBuf::CWQuitTeamReq quitTeamReq;
	ProtoBuf::WCQuitTeamRsp quitTeamRsp;

	if (!quitTeamReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWQuitTeamReq parse failed...");
		return false;
	}

	QuitTeam(charId);
	//ProtoBuf::ERetCode ret = QuitTeam(charId);

	//quitTeamRsp.set_ret(ret);
	//g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_QUIT_TEAM, &quitTeamRsp);
	
	return true;
}

bool TeamManager::HandleInviteJoin(CharIDType charId, RECV_PACKAGE& package)
{
	ProtoBuf::CWInviteJoinReq inviteJoinReq;
	ProtoBuf::WCInviteJoinRsp inviteJoinRsp;

	if (!inviteJoinReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWInviteJoinReq parse failed...");
		return false;
	}

	CharIDType dstId = inviteJoinReq.playerid();

	ProtoBuf::ERetCode ret = InviteJoin(charId, dstId);
	inviteJoinRsp.set_ret(ret);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_INVITE_JOIN, &inviteJoinRsp);

	return true;
}

bool TeamManager::HandleInviteJoinEchoReq(CharIDType charId, RECV_PACKAGE& package)
{
	ProtoBuf::CWInviteJoinEchoReq inviteJoinEchoReq;
	ProtoBuf::CWInviteJoinEchoRsp inviteJoinEchoRsp;

	if (!inviteJoinEchoReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWInviteJoinEchoReq parse failed...");
		return false;
	}

	ProtoBuf::ERetCode ret = RET_SUCCESS;
	ret = InviteJoinEcho(charId, inviteJoinEchoReq.echolist().playerid(), inviteJoinEchoReq.echolist().teamid(), inviteJoinEchoReq.echolist().result());
	inviteJoinEchoRsp.set_ret(ret);
	inviteJoinEchoRsp.mutable_echolist()->CopyFrom(inviteJoinEchoReq.echolist());
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_INVITE_JOIN_ECHO, &inviteJoinEchoRsp);
	return true;
}

bool TeamManager::HandleDeleteMember(CharIDType charId, RECV_PACKAGE& package)
{
	ProtoBuf::CWDeleteMemberReq deleteMemberReq;
	ProtoBuf::CWDeleteMemberRsp deleteMemberRsp;

	if (!deleteMemberReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWDeleteMemberReq parse failed...");
		return false;
	}

	CharIDType deleteId = deleteMemberReq.playerid();
	ProtoBuf::ERetCode ret = DeleteMember(charId, deleteId);

	deleteMemberRsp.set_ret(ret);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_DELETE_MEMBER, &deleteMemberRsp);
	
	return true;
}

bool TeamManager::HandleTransferTeam(CharIDType charId, RECV_PACKAGE& package)
{
	ProtoBuf::CWTransferTeamReq transferReq;
	ProtoBuf::WCTeamSettingRsp  transferRsp;

	if (!transferReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWTransferTeamReq parse failed...");
		return false;
	}

	CharIDType newLeaderId = transferReq.playerid();
	ProtoBuf::ERetCode ret = TransferLeader(charId, newLeaderId);

	transferRsp.set_ret(ret);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TRANSFER_TEAM, &transferRsp);

	return true;
}

bool TeamManager::HandleTeamSetting(CharIDType charId, RECV_PACKAGE& package)
{
	ProtoBuf::CWTeamSettingReq teamSettingReq;
	ProtoBuf::WCTeamSettingRsp teamSettingRsp;

	if (!teamSettingReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CGTeamSettingReq parse failed...");
		return false;
	}
	
	uint32_t teamObject = teamSettingReq.teamobject();
	uint32_t minLv = teamSettingReq.minlv();
	uint32_t maxLv = teamSettingReq.maxlv();

	ProtoBuf::ERetCode ret = TeamSetting(charId, teamObject, minLv, maxLv);
	teamSettingRsp.set_ret(ret);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_SETTING, &teamSettingRsp);

	if (RET_SUCCESS != ret)
	{
		return true;
	}
	
	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
	{
		return true;
	}

	TeamMember* memberList = myTeam->GetMemberList();
	if (nullptr == memberList)	
	{
		return true;
	}

	uint32_t count = myTeam->MemberCount();
	for (uint32_t i = 0; i != count; ++i)
	{
		if (memberList[i].playerId == charId)	
			continue;

		ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(memberList[i].playerId);
		if (nullptr == pActiveCharacter)	
			continue;

		ProtoBuf::WCUpdateTeamInfoNotify notify;
		GetTeamInfo(pActiveCharacter, *(notify.mutable_teaminfo()));
		g_GetCenterService()->SendDataToClient(memberList[i].playerId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_UPDATE_TEAM_INFO_NOTIFY, &notify);
	}
	
	return true;
}

bool TeamManager::HandleAutoMatchReq(CharIDType charId, RECV_PACKAGE& package)
{
	ProtoBuf::WCAutoMatchReq autoMatchReq;
	//ProtoBuf::WCAutoMatchRsp autoMatchRsp;

	if (!autoMatchReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("WCAutoMatchReq parse failed...");
		return false;
	}

	CharIDType teamObjectId = autoMatchReq.teamobject();
	uint32_t isAutoMatch = autoMatchReq.isautomatch();
	AutoMatch(charId, teamObjectId, isAutoMatch);

	/*autoMatchRsp.set_ret(ret);
	autoMatchRsp.set_isautomatch(isAutoMatch);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_AUTO_MATCH, &autoMatchRsp);*/

	return true;
}

bool TeamManager::HandleApplyListReq(CharIDType charId, RECV_PACKAGE& package)
{
	ProtoBuf::CWTeamApplyListReq applyListReq;
	ProtoBuf::WCTeamApplyListRsp applyListRsp;

	if (!applyListReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWTeamApplyListReq parse failed...");
		return false;
	}

	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam || !myTeam->IsMember(charId))
	{
		applyListRsp.set_ret(RET_TEAM_NO_TEAM);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_APPLY_LIST, &applyListRsp);
		return false;
	}

	//if (!myTeam->IsLeader(charId))
	//{
	//	applyListRsp.set_ret(RET_TEAM_NO_AUTHORITY);
	//	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_APPLY_LIST, &applyListRsp);
	//	return false;
	//}

	std::vector<CharIDType> applyList;
	myTeam->GetApplicant(applyList);

	for (uint32_t i = 0; i < applyList.size(); i++)
	{
		OfflineCharacterData *pOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(applyList[i]);
		if (nullptr == pOfflineCharacterData)
		{
			continue;
		}

		ProtoBuf::TeamMemberInfo* member = applyListRsp.add_applylist();
		if (nullptr == member)
		{
			LogErrFmtPrint("TeamManager::HandleApplyListReq...cid:%lu ", charId);
			continue;
		}
		member->set_playerid(applyList[i]);
		member->set_name(pOfflineCharacterData->GetCharName());
		member->set_level(pOfflineCharacterData->GetLevel());
		member->set_profession(pOfflineCharacterData->GetProf());
		member->set_sex(pOfflineCharacterData->GetSex());
		member->set_fightpower(pOfflineCharacterData->GetFight());
		member->set_campid(pOfflineCharacterData->GetCampID());
		member->mutable_facade()->CopyFrom(pOfflineCharacterData->GetFacade());
	}

	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_APPLY_LIST, &applyListRsp);

	return true;
}

bool TeamManager::HandleClearApplyListReq(CharIDType charId, RECV_PACKAGE& package)
{
	ProtoBuf::CWClearTeamApplyListReq clearApplyListReq;
	ProtoBuf::CWClearTeamApplyListRsp clearApplyListRsp;

	if (!clearApplyListReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWClearTeamApplyListReq parse failed...");
		return false;
	}

	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam || !myTeam->IsMember(charId))
	{
		clearApplyListRsp.set_ret(RET_TEAM_NO_TEAM);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_CLEAR_APPLY_LIST, &clearApplyListRsp);
		return false;
	}

	if (!myTeam->IsLeader(charId))
	{
		clearApplyListRsp.set_ret(RET_TEAM_NO_AUTHORITY);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_CLEAR_APPLY_LIST, &clearApplyListRsp);
		return false;
	}

	myTeam->ClearApplicant();
	clearApplyListRsp.set_ret(RET_SUCCESS);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_CLEAR_APPLY_LIST, &clearApplyListRsp);
	return true;
}

bool TeamManager::HandleTeamFollowReq(CharIDType charId, RECV_PACKAGE& package)
{
	ProtoBuf::CWTeamFollowReq teamFollowReq;
	ProtoBuf::WCTeamFollowRsp teamFollowRsp;
	ProtoBuf::WCTeamFollowNotify teamFollowNotify;

	if (!teamFollowReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWTeamFollowReq parse failed...");
		return false;
	}

	//广播队伍队长召唤跟随
	ProtoBuf::ERetCode ret = CallFollowTeam(charId);
	teamFollowRsp.set_ret(ret);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_FOLLOW, &teamFollowRsp);


	/*ProtoBuf::ERetCode ret = FollowTeam(charId);
	teamFollowRsp.set_ret(ret);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_FOLLOW, &teamFollowRsp);

	//如果成功发送到队长通知其他队员
	//if (ret == RET_SUCCESS)
	//{
	//	teamFollowNotify.set_leaderid(charId);
	//	BroadcastTeam(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_FOLLOW_NOTIFY, &teamFollowNotify);
	//}

	//同步队长位置坐标
	if (RET_SUCCESS == ret)
	{
		//拉取队长坐标
		ProtoBuf::WGLeaderPosInfoReq logicReq;
		logicReq.set_leaderid(charId);
		g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_TEAM, CENTER_TO_LOGIC_LEADER_POS_INFO, &logicReq);
	}*/
	
	return true;
}

bool TeamManager::HandleLeaderPosInfoReq(CharIDType charId, RECV_PACKAGE& package)
{
	ProtoBuf::CWLeaderPosInfoReq clientReq;
	ProtoBuf::WCLeaderPosInfoRsp clientRsp;

	if (!clientReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWLeaderPosInfoReq parse failed...");
		return false;
	}

	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
	{
		clientRsp.set_ret(RET_TEAM_NO_EXIST);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_LEADER_POS_INFO, &clientRsp);
		return false;
	}

	if (nullptr != myTeam && !myTeam->IsMember(charId))
	{
		clientRsp.set_ret(RET_TEAM_NO_EXIST);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_LEADER_POS_INFO, &clientRsp);
		return false;
	}

	//队长不能获取位置坐标了
	if (myTeam->IsLeader(charId))
	{
		clientRsp.set_ret(RET_FAIL);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_LEADER_POS_INFO, &clientRsp);
		return false;
	}

	//队长已经下线了
	ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(myTeam->Leader());
	if (nullptr == pActiveCharacter)
	{
		clientRsp.set_ret(RET_NOT_ONLINE);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_LEADER_POS_INFO, &clientRsp);
		return false;
	}

	ProtoBuf::WGLeaderPosInfoReq logicReq;
	logicReq.set_leaderid(myTeam->Leader());
	logicReq.set_charid(charId);
	g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_TEAM, CENTER_TO_LOGIC_LEADER_POS_INFO, &logicReq);

	return true;
}

bool TeamManager::HandleTeamEnsureFollowReq(CharIDType charId, RECV_PACKAGE& package)
{
	ProtoBuf::CWTeamEnsureFollowReq teamEnsureFollowReq;
	ProtoBuf::WCTeamEnsureFollowRsp teamEnsureFollowRsp;

	if (!teamEnsureFollowReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWTeamEnsureFollowReq parse failed...");
		return false;
	}

	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
	{
		teamEnsureFollowRsp.set_ret(RET_TEAM_NO_EXIST);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_ENSURE_FOLLOW, &teamEnsureFollowRsp);
		return false;
	}

	if (nullptr != myTeam && !myTeam->IsMember(charId))
	{
		teamEnsureFollowRsp.set_ret(RET_TEAM_NO_EXIST);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_ENSURE_FOLLOW, &teamEnsureFollowRsp);
		return false;
	}

	if (myTeam->IsLeader(charId))
	{
		teamEnsureFollowRsp.set_ret(RET_FAIL);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_ENSURE_FOLLOW, &teamEnsureFollowRsp);
		return false;
	}

	ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pActiveCharacter)
	{
		teamEnsureFollowRsp.set_ret(RET_NOT_ONLINE);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_ENSURE_FOLLOW, &teamEnsureFollowRsp);
		return false;
	}

	if (pActiveCharacter->GetLifeStatus() == State_dead)
	{
		teamEnsureFollowRsp.set_ret(RET_FAIL);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_ENSURE_FOLLOW, &teamEnsureFollowRsp);
		return false;
	}

	//队员在副本场景 屏蔽跟随请求
	uint32_t mapId = pActiveCharacter->GetMapID();
	const MapMapCfgInfo*  pMapCfg = g_GetMapMapCfgTable()->GetMapMapCfgInfo(mapId);
	if (nullptr == pMapCfg || (pMapCfg->mapType == DYNAMIC_MAP && !g_GetMapCfgMgr()->IsUnionDunGeonMap(mapId) && !g_GetMapCfgMgr()->IsUnionHomeMap(mapId)))
	{
		teamEnsureFollowRsp.set_ret(RET_TEAM_DYNAMIC_MAP_NOT_FOLLOW);
		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_ENSURE_FOLLOW, &teamEnsureFollowRsp);
		return false;
	}

	bool isFollow = teamEnsureFollowReq.isfollow();
	if (isFollow)
	{
		if (myTeam->SceneID() != pActiveCharacter->GetSceneID())
		{
			teamEnsureFollowRsp.set_ret(RET_TEAM_NOT_SAME_NOT_FOLLOW);
			g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_ENSURE_FOLLOW, &teamEnsureFollowRsp);
			return false;
		}
	}

	myTeam->SetFollow(charId, isFollow);
	teamEnsureFollowRsp.set_ret(RET_SUCCESS);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_ENSURE_FOLLOW, &teamEnsureFollowRsp);

	//是跟随才要拉取队长位置坐标
	if (isFollow)
	{
		ProtoBuf::WGLeaderPosInfoReq logicReq;
		logicReq.set_leaderid(myTeam->Leader());
		logicReq.set_charid(charId);
		g_GetCenterService()->SendDataToLogicByCharID(myTeam->Leader(), EMODULE_ID_TEAM, CENTER_TO_LOGIC_LEADER_POS_INFO, &logicReq);
	}

	WCTeamEnsureFollowNotify ensureFollowNotify;
	ensureFollowNotify.set_charid(charId);
	ensureFollowNotify.set_isfollow(isFollow);
	//通知非跟随状态的成员
	BroadcastTeam(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_ENSURE_FOLLOW_NOTIFY, &ensureFollowNotify, false, true);

	return true;
}

bool TeamManager::HandleTeamCancelFollowReq(CharIDType charId, RECV_PACKAGE& package)
{
	ProtoBuf::CWCancelFollowReq cancelFollowReq;
	ProtoBuf::WCCancelFollowRsp cancelFollowRsp;

	if (!cancelFollowReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("CWCancelFollowReq parse failed...");
		return false;
	}

	ProtoBuf::ERetCode ret = CancelFollowTeam(charId);
	cancelFollowRsp.set_ret(ret);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_CANCEL_FOLLOW, &cancelFollowRsp);

	if (ret == RET_SUCCESS)
	{
		ProtoBuf::WCCancelFollowNotify cancelFollowNotify;
		cancelFollowNotify.set_leaderid(charId);
		BroadcastTeam(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_CANCEL_FOLLOW_NOTIFY, &cancelFollowNotify);
	}


	return true;
}

bool TeamManager::HandleStarSoulReponse(CharIDType charId, RECV_PACKAGE& package)
{
	ProtoBuf::StarSoulSendReq sendReq;
	ProtoBuf::WGStarSoulSend wgSend;

	if (!sendReq.ParseFromArray(package.dataAfterHead, package.sizeAfterHead))
	{
		MMOLOG_FMT_ERROR("StarSoulSendReq parse failed...");
		return false;
	}

	uint64_t leaderId = sendReq.leader_id();
	Team* myTeam = FindTeam(leaderId);
	if (nullptr == myTeam || !myTeam->IsLeader(leaderId))
	{
		StarSoulSendRsp rsp;
		rsp.set_retcode(RET_TEAM_STAR_SOUL_SEND_ERROR);
		return g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, LOGIC_TO_CLIENT_STAR_SOUL_RESP, &rsp);
	}

	if (!myTeam->IsMember(charId))
	{
		StarSoulSendRsp rsp;
		rsp.set_retcode(RET_TEAM_NO_TEAM);
		return g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, LOGIC_TO_CLIENT_STAR_SOUL_RESP, &rsp);
	}

	wgSend.set_charid(charId);
	wgSend.set_type(sendReq.type());
	wgSend.set_map_id(sendReq.map_id());
	wgSend.mutable_cur_pos()->CopyFrom(sendReq.cur_pos());
	return g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_TEAM, CENTER_TO_LOGIC_STAR_SOUL_SEND, &wgSend);
}

ProtoBuf::ERetCode TeamManager::CreateTeam(CharIDType charId)
{
	Team* myTeam = FindTeam(charId);
	if (nullptr != myTeam && myTeam->IsMember(charId))
	{
		return RET_TEAM_REPEAT_CREATE;
	}

	OfflineCharacterData *pOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOfflineCharacterData)
	{
		return RET_FAIL;
	}

	if (!CheckCreateLevel(pOfflineCharacterData->GetLevel()))
	{
		return RET_TEAM_CREATE_LEVEL_ERROR;
	}

	ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pActiveCharacter)
	{
		return RET_FAIL;
	}

	if (CheckInJail(pActiveCharacter->GetMapID()))
	{
		return RET_TEAM_JAIL_SCENE_ERROR_SELF;
	}

	uint32_t sceneId = pActiveCharacter->GetSceneID();
	Team* team = CreateTeamEx();
	if (nullptr == team)
	{
		return RET_FAIL;
	}

	TeamID_t teamId = CreateTeamId();

	TeamMember* member = nullptr;
	bool success = team->AddMember(charId, member);
	if (!success)
	{
		RecoverTeam(team);
		return RET_TEAM_CREATE_LEVEL_ERROR;
	}

	team->SetTeamID(teamId);
	team->SetSceneID(sceneId);
	team->SetLeader(charId);

	//设置队伍默认类型
	const TeamTeamCfgInfo* teamCfgInfo = g_MakeTeamCfgMgr()->GetTeamInitCfgInfo();
	if (nullptr != teamCfgInfo)
	{
		team->SetTeamObjectId(teamCfgInfo->TeamObjectID);
		team->SetJoinMinLvLimit((int16_t)teamCfgInfo->LowLV);
		team->SetJoinMaxLvLimit((int16_t)teamCfgInfo->UpLV);
	}

	//设置玩家和队伍ID的映射
	AddIndex(charId, teamId);

	member->identity = IDENTITY_LEAGER;
	member->sceneId = sceneId;

	_teamList[teamId] = team;
	//_teamList.insert(std::make_pair(teamId, team));
	AddToScene(sceneId, teamId);

	//创建队伍成功后移除玩家自动匹配
	CancelCharacterAutoMatch(charId);

	//向逻辑服通知队伍信息
	SendSynTeamNotify(charId);

	//向创建者发送创建队伍通知
	ProtoBuf::WCCreateTeamNotify createTeamNotify;
	GetTeamInfo(pActiveCharacter, *(createTeamNotify.mutable_teaminfo()));
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_CREATE_TEAM_NOTIFY, &createTeamNotify);

	return RET_SUCCESS;
}

ProtoBuf::ERetCode TeamManager::QueryTeam(CharIDType charId)
{
	ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pActiveCharacter)
	{
		return RET_FAIL;
	}

	Team* myTeam = FindTeam(charId);
	//如果没有队伍
	if (nullptr == myTeam)
	{
		return RET_TEAM_NO_EXIST;
	}

	//如果有队伍但不是该队伍的成员 那么要重新将该玩家的队伍ID设置为无效
	if (!myTeam->IsMember(charId))
	{
		SetCharcterTeamId(charId, INVALID_TEAM_ID);
		return RET_TEAM_NO_EXIST;
	}

	ProtoBuf::WCUpdateTeamInfoNotify notify;
	//自己的队伍信息
	GetTeamInfo(pActiveCharacter, *(notify.mutable_teaminfo()));
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_UPDATE_TEAM_INFO_NOTIFY, &notify);

	return RET_SUCCESS;

}

ProtoBuf::ERetCode TeamManager::QueryOtherTeam(CharIDType charId, uint32_t type, uint32_t subType)
{
	if (type == 0) //0默认表示查询同场景的
	{
		return QuerySameSceneTeam(charId, type, subType);
	}
	

	return QuerySameTypeTeam(charId, type, subType);
}

ProtoBuf::ERetCode TeamManager::QuerySameSceneTeam(CharIDType charId, uint32_t type, uint32_t subType)
{
	ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pActiveCharacter)
	{
		return RET_FAIL;
	}

	OfflineCharacterData *pMyOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pMyOfflineCharacterData)
	{
		return RET_FAIL;
	}

	//同地图其他队伍列表
	ProtoBuf::WCQueryOhterTeamRsp response;
	uint32_t sceneId = pActiveCharacter->GetSceneID();
	TeamID_t myTeamId = GetTeamId(charId);
	SceneTeamList::const_iterator sceneIter = _sceneTeamList.find(sceneId);
	if (_sceneTeamList.end() != sceneIter)
	{
		TeamIdList::const_iterator idIter = sceneIter->second.begin();
		for (; sceneIter->second.end() != idIter; ++idIter)
		{
			if (*idIter == myTeamId)
			{
				continue;
			}

			Team* otherTeam = FindTeamById(*idIter);
			if (NULL != otherTeam  && !otherTeam->IsFull())
			{
				CharIDType leaderId = otherTeam->Leader();
				OfflineCharacterData *pOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(leaderId);
				if (nullptr == pOfflineCharacterData)
				{
					continue;
				}

				/*if (pOfflineCharacterData->GetCampID() != pMyOfflineCharacterData->GetCampID())
				{
					continue;
				}*/

				if (pMyOfflineCharacterData->GetLevel() < otherTeam->GetJoinMinLvLimit() || pMyOfflineCharacterData->GetLevel() > otherTeam->GetJoinMaxLvLimit())
				{
					continue;
				}

				ProtoBuf::OtherTeamInfo* teamInfo = response.add_teamlist();
				if (nullptr == teamInfo)
				{
					LogErrFmtPrint("TeamManager::QuerySameSceneTeam..nullptr == teamInfo...cid:%lu, type:%d, subtype:%d  ", charId, type, subType);
					continue;
				}
				teamInfo->set_id(otherTeam->TeamID());
				teamInfo->set_sceneid(otherTeam->SceneID());
				teamInfo->set_leaderid(otherTeam->Leader());
				teamInfo->set_count(otherTeam->MemberCount());
				teamInfo->set_name(pOfflineCharacterData->GetCharName());
				teamInfo->set_level(pOfflineCharacterData->GetLevel());
				teamInfo->set_prof(pOfflineCharacterData->GetProf());
				teamInfo->set_sex(pOfflineCharacterData->GetSex());

				uint32_t count = otherTeam->MemberCount();
				TeamMember* list = otherTeam->GetMemberList();
				if (nullptr != list)
				{
					for (uint32_t i = 0; i != count; ++i)
					{
						if (otherTeam->Leader() == list[i].playerId)
						{
							continue;
						}

						OfflineCharacterData *pMemOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(list[i].playerId);
						if (nullptr == pMemOfflineCharacterData)
						{
							continue;
						}

						ProtoBuf::TeamMemberInfo* member = teamInfo->add_memberlist();
						if (nullptr == member)
						{
							LogErrFmtPrint("TeamManager::QuerySameSceneTeam... nullptr == member charId:%lu type:%d, subtype:%d ", charId, type, subType);
							continue;
						}
						member->set_playerid(list[i].playerId);
						member->set_level(pMemOfflineCharacterData->GetLevel());
						member->set_profession(pMemOfflineCharacterData->GetProf());
						member->set_sex(pMemOfflineCharacterData->GetSex());
					}
				}				
			}
		}
	}

	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_QUERY_OTHER_TEAM, &response);

	return RET_SUCCESS;
}

ProtoBuf::ERetCode TeamManager::QuerySameTypeTeam(CharIDType charId, uint32_t type, uint32_t subType)
{
	ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pActiveCharacter)
	{
		return RET_FAIL;
	}

	OfflineCharacterData *pMyOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pMyOfflineCharacterData)
	{
		return RET_FAIL;
	}

	ProtoBuf::WCQueryOhterTeamRsp response;
	TeamID_t myTeamId = GetTeamId(charId);
	uint32_t teamObject = g_GetTeamCfgMgr()->GetTeamObject(type, subType);
	if (INVALID_TEAM_OBJECT_ID != teamObject)
	{
		TeamObjectMap::iterator typeIter = _teamTypeIdMap.find(teamObject);
		if (typeIter != _teamTypeIdMap.end())
		{
			TeamSet::const_iterator idIter = typeIter->second.begin();
			for (; typeIter->second.end() != idIter; ++idIter)
			{
				if (nullptr == *idIter)
				{
					continue;
				}

				//过滤掉同队伍的
				if ((*idIter)->TeamID() == myTeamId)
				{
					continue;
				}

				if (nullptr != *idIter  && !(*idIter)->IsFull())
				{
					CharIDType leaderId = (*idIter)->Leader();
					OfflineCharacterData *pOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(leaderId);
					if (nullptr == pOfflineCharacterData)
					{
						continue;
					}

					/*if (pOfflineCharacterData->GetCampID() != pMyOfflineCharacterData->GetCampID())
					{
						continue;
					}*/

					if (pMyOfflineCharacterData->GetLevel() < (*idIter)->GetJoinMinLvLimit() || pMyOfflineCharacterData->GetLevel() > (*idIter)->GetJoinMaxLvLimit())
					{
						continue;
					}

					ProtoBuf::OtherTeamInfo* teamInfo = response.add_teamlist();
					if (nullptr == teamInfo)
					{
						LogErrFmtPrint("TeamManager::QuerySameTypeTeam...nullptr == teamInfo cid:%lu ,type:%d, subtype:%d ", charId, type, subType);
						continue;
					}
					teamInfo->set_id((*idIter)->TeamID());
					teamInfo->set_sceneid((*idIter)->SceneID());
					teamInfo->set_leaderid((*idIter)->Leader());
					teamInfo->set_count((*idIter)->MemberCount());
					teamInfo->set_name(pOfflineCharacterData->GetCharName());
					teamInfo->set_level(pOfflineCharacterData->GetLevel());
					teamInfo->set_prof(pOfflineCharacterData->GetProf());
					teamInfo->set_sex(pOfflineCharacterData->GetSex());

					uint32_t count = (*idIter)->MemberCount();
					TeamMember* list = (*idIter)->GetMemberList();
					if (nullptr != list)
					{
						for (uint32_t i = 0; i != count; ++i)
						{
							if ((*idIter)->Leader() == list[i].playerId)
							{
								continue;
							}

							OfflineCharacterData *pMemOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(list[i].playerId);
							if (nullptr == pMemOfflineCharacterData)
							{
								continue;
							}

							ProtoBuf::TeamMemberInfo* member = teamInfo->add_memberlist();
							if (nullptr == member)
							{
								LogErrFmtPrint("TeamManager::QuerySameTypeTeam...nullptr == member cid:%lu ,type:%d, subtype:%d ", charId, type, subType);
								continue;
							}
							member->set_playerid(list[i].playerId);
							member->set_level(pMemOfflineCharacterData->GetLevel());
							member->set_profession(pMemOfflineCharacterData->GetProf());
							member->set_sex(pMemOfflineCharacterData->GetSex());
						}
					}					
				}
			}
		}
	}

	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_QUERY_OTHER_TEAM, &response);

	return RET_SUCCESS;
}

ProtoBuf::ERetCode TeamManager::JoinTeam(CharIDType charId, CharIDType dstId)
{
	Team* myTeam = FindTeam(charId);
	if (nullptr != myTeam && myTeam->IsMember(charId))
	{
		return RET_TEAM_REPEAT_JOIN;
	}

	OfflineCharacterData *pOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
	if (nullptr == pOfflineCharacterData)
	{
		return RET_FAIL;
	}

	OfflineCharacterData *pDstOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(dstId);
	if (nullptr == pDstOfflineCharacterData)
	{
		return RET_FAIL;
	}

	ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pActiveCharacter)
	{
		return RET_FAIL;
	}

	if (CheckInJail(pActiveCharacter->GetMapID()))
	{
		return RET_TEAM_JAIL_SCENE_ERROR_SELF;
	}

	/*if (pOfflineCharacterData->GetCampID() != pDstOfflineCharacterData->GetCampID())
	{
		return RET_TEAM_NOT_SAME_CAMP;
	}*/

	//检查被加入方的队伍是否存在
	Team* dstTeam = FindTeam(dstId);
	if (nullptr == dstTeam)
	{
		return RET_TEAM_NO_EXIST;
	}

	if (pOfflineCharacterData->GetLevel() < dstTeam->GetJoinMinLvLimit() || pOfflineCharacterData->GetLevel() > dstTeam->GetJoinMaxLvLimit())
	{
		return RET_TEAM_CREATE_LEVEL_ERROR;
	}

	//判断队伍是否已经满员了
	if (dstTeam->IsFull())
	{
		return RET_TEAM_FULL;
	}

	//之前没有申请过的加入到申请列表
	if (!dstTeam->HaveApplicant(charId))
	{
		if (!dstTeam->AddApplicant(charId))
		{
			return RET_TEAM_APPLICANT_LIMIT;
		}
	}

	//发送申请通知给对方
	ProtoBuf::WCApplyJoinNotify notify;
	ProtoBuf::TeamMemberInfo* member = notify.mutable_applicant();
	if (nullptr != member)
	{
		member->set_playerid(charId);
		member->set_name(pOfflineCharacterData->GetCharName());
		member->set_level(pOfflineCharacterData->GetLevel());
		member->set_profession(pOfflineCharacterData->GetProf());
		member->set_sex(pOfflineCharacterData->GetSex());
		member->set_fightpower(pOfflineCharacterData->GetFight());
		member->set_campid(pOfflineCharacterData->GetCampID());
		member->mutable_facade()->CopyFrom(pOfflineCharacterData->GetFacade());

		//发送通知给队长
		CharIDType leaderId = dstTeam->Leader();
		g_GetCenterService()->SendDataToClient(leaderId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_APPLY_JOIN_NOTIFY, &notify);
	}
	else
	{
		LogErrFmtPrint("TeamManager::JoinTeam...nullptr == member cid:%lu ,dstid:%lu ", charId, dstId);
	}
	
	return RET_SUCCESS;
}

ProtoBuf::ERetCode TeamManager::JoinTeamEcho(CharIDType charId, const std::vector<CharIDType>& agreeList)
{
	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
	{
		return RET_TEAM_NO_EXIST;
	}

	if (!myTeam->IsMember(charId))
	{
		SetCharcterTeamId(charId, INVALID_TEAM_ID);
		return RET_TEAM_NO_EXIST;
	}

	if (!myTeam->IsLeader(charId))
	{
		return RET_TEAM_NO_AUTHORITY;
	}

	for (uint32_t i = 0; i != agreeList.size(); ++i)
	{
		CharIDType dstId = agreeList[i];

		if (!myTeam->HaveApplicant(dstId))
		{
			return RET_TEAM_NO_IN_APPLICANT;
		}

		ProtoBuf::ERetCode ret = AddToTeam(myTeam, dstId);
		if (RET_SUCCESS == ret) //加入成功后移除该玩家自动匹配设置
		{
			CancelCharacterAutoMatch(dstId);
		}
		else
		{
			return ret;
		}
	}

	return RET_SUCCESS;
}

ProtoBuf::ERetCode TeamManager::DisagreeTeamEcho(CharIDType charId, const std::vector<CharIDType>& disagreeList)
{
	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
	{
		return RET_TEAM_REPEAT_JOIN;
	}

	if (!myTeam->IsMember(charId))
	{
		return RET_TEAM_REPEAT_JOIN;
	}

	if (!myTeam->IsLeader(charId))
	{
		return RET_TEAM_NO_AUTHORITY;
	}

	for (uint32_t i = 0; i != disagreeList.size(); ++i)
	{
		CharIDType dstId = disagreeList[i];
		myTeam->DelApplicant(dstId);
	}

	return RET_SUCCESS;
}

ProtoBuf::ERetCode TeamManager::QuitTeam(CharIDType charId)
{
	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
	{
		return RET_TEAM_NO_EXIST;
	}

	if (!myTeam->IsMember(charId))
	{
		SetCharcterTeamId(charId, INVALID_TEAM_ID);
		return RET_TEAM_NO_EXIST;
	}

	bool isLeader = false;
	//如果离队的是队长任命新队长
	if (myTeam->IsLeader(charId) && myTeam->MemberCount() > 1)
	{
		isLeader = true;
	}
	
	//移除队员
	myTeam->DelMember(charId);
	RemoveIndex(charId);

	if (isLeader)
	{
		//转让队长
		CharIDType newLeader = myTeam->ChangeLeader();
		ChangeLeader(myTeam, newLeader);
	}

	ProtoBuf::WCMemberQuitNotify notify;
	notify.set_playerid(charId);

	if (!myTeam->IsValid())
	{
		//解散队伍操作
		CancelTeam(myTeam->TeamID());

		//向场景服同步信息
		SendSynTeamNotify(charId);

		g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_MEMBER_QUIT_NOTIFY, &notify);
	}
	else
	{
		//发送离队通知给其它队友
		TeamMember* memberList = myTeam->GetMemberList();
		if (nullptr != memberList)
		{
			uint32_t count = myTeam->MemberCount();
			for (uint32_t i = 0; i != count; ++i)
			{
				g_GetCenterService()->SendDataToClient(memberList[i].playerId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_MEMBER_QUIT_NOTIFY, &notify);

				//向场景服同步信息
				SendSynTeamNotify(memberList[i].playerId);
			}
		}	

		//向场景服同步信息
		SendSynTeamNotify(charId);
	}

	ProtoBuf::WCQuitTeamRsp quitTeamRsp;
	quitTeamRsp.set_ret(RET_SUCCESS);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_QUIT_TEAM, &quitTeamRsp);

	return RET_SUCCESS;
}

ProtoBuf::ERetCode TeamManager::InviteJoin(CharIDType inviteId, CharIDType dstId)
{
	//邀请方离线数据出错
	OfflineCharacterData *pInviteOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(inviteId);
	if (nullptr == pInviteOfflineCharacterData)
	{
		return RET_FAIL;
	}

	//判断对方是否在线
	ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(dstId);
	if (nullptr == pActiveCharacter)
	{
		return RET_PLAYER_NOT_ONLINE;
	}

	//对方离线数据出错
	OfflineCharacterData *pDstOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(dstId);
	if (nullptr == pDstOfflineCharacterData)
	{
		return RET_FAIL;
	}

	if (CheckInJail(pActiveCharacter->GetMapID()))
	{
		return RET_TEAM_JAIL_SCENE_ERROR_OTHER;
	}

	//判断对方是否已经有队伍
	Team* otherTeam = FindTeam(dstId);
	if (NULL != otherTeam && otherTeam->IsMember(dstId))
	{
		return RET_TEAM_INVITEE_REPEAT_JOIN;
	}

	//判断阵营ID
	/*if (pInviteOfflineCharacterData->GetCampID() != pDstOfflineCharacterData->GetCampID())
	{
		return RET_TEAM_NOT_SAME_CAMP;
	}*/

	Team* myTeam = FindTeam(inviteId);
	if (nullptr == myTeam)
	{
		//如果没有队伍那么创建队伍
		ProtoBuf::ERetCode ret = CreateTeam(inviteId);
		if (RET_SUCCESS != ret)
		{
			return ret;
		}
	}

	myTeam = FindTeam(inviteId);
	if (nullptr == myTeam)
	{
		return RET_TEAM_NO_EXIST;
	}

	//判断等级
	if (pDstOfflineCharacterData->GetLevel() < myTeam->GetJoinMinLvLimit() || pDstOfflineCharacterData->GetLevel() > myTeam->GetJoinMaxLvLimit())
	{
		return RET_TEAM_CREATE_LEVEL_ERROR;
	}

	if (nullptr != myTeam && !myTeam->IsMember(inviteId))
	{
		//不可邀请
		return RET_TEAM_NO_INVITE;
	}

	if (nullptr != myTeam && myTeam->IsMember(dstId))
	{
		//不可邀请
		return RET_TEAM_OTHER_ALREADY_JOIN;
	}

	if (dstId == inviteId)
	{
		//自己
		return RET_TEAM_REPEAT_JOIN;
	}

	if (g_GetRoomMgr()->getCharRoom(dstId) > 0)
	{
		return RET_TEAM_NO_APPLY_IN_ROOM;
	}


	ProtoBuf::WCInviteJoinNotify notify;
	ProtoBuf::TeamMemberInfo* member = notify.mutable_inviterinfo();
	if (nullptr != member)
	{
		member->set_playerid(inviteId);
		member->set_name(pInviteOfflineCharacterData->GetCharName());
		member->set_level(pInviteOfflineCharacterData->GetLevel());
		member->set_profession(pInviteOfflineCharacterData->GetProf());
		member->set_sex(pInviteOfflineCharacterData->GetSex());
		member->set_fightpower(pInviteOfflineCharacterData->GetFight());
		member->set_campid(pInviteOfflineCharacterData->GetCampID());
		member->mutable_facade()->CopyFrom(pInviteOfflineCharacterData->GetFacade());
		member->set_teamid(myTeam->TeamID());
		notify.set_type(myTeam->GetTeamObjectId());
		g_GetCenterService()->SendDataToClient(dstId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_INVITE_JOIN_NOTIFY, &notify);
	}
	else
	{
		LogErrFmtPrint("TeamManager::InviteJoin..nullptr == member  invite:%lu,dst:%lu ", inviteId, dstId);
	}

	return RET_SUCCESS;

}

ProtoBuf::ERetCode TeamManager::InviteJoinEcho(CharIDType charId, CharIDType inviteId, TeamID_t inviteTeamId, uint32_t result)
{
	if (result == TEAM_ECHO_Y)
	{
		Team* myTeam = FindTeam(charId);
		//如果被邀请方已经有队伍了
		if (nullptr != myTeam && myTeam->IsMember(charId))
		{
			return RET_TEAM_REPEAT_CREATE;
		}
		else
		{
			Team* inviterTeam = nullptr;
			//如果邀请方没有队伍了那么直接返回队伍不存在
			inviterTeam = FindTeam(inviteId);
			if (nullptr == inviterTeam)
			{
				return RET_TEAM_NO_EXIST;
			}

			if (inviterTeam->TeamID() != inviteTeamId)
			{
				return RET_TEAM_NO_EXIST;
			}

			ProtoBuf::ERetCode ret = RET_FAIL;
			//如果队长已经不是邀请方了说明可能队长转让过，此时返回队伍不存在
			//邀请方可能是队长可能是队员 若是队长做入队处理,若是队员则加入队伍申请列表
			if (!inviterTeam->IsLeader(inviteId))
			{
				OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
				if (nullptr == pOffline)
					return RET_NOT_HAVE_CHARACTER;

				if (!inviterTeam->AddApplicant(charId))
					return RET_TEAM_APPLICANT_LIMIT;

				//发送新增申请人给队长
				ProtoBuf::WCApplyJoinNotify notify;
				ProtoBuf::TeamMemberInfo* member = notify.mutable_applicant();
				if (nullptr != member)
				{
					member->set_playerid(charId);
					member->set_name(pOffline->GetCharName());
					member->set_level(pOffline->GetLevel());
					member->set_profession(pOffline->GetProf());
					member->set_sex(pOffline->GetSex());
					member->set_fightpower(pOffline->GetFight());
					member->set_campid(pOffline->GetCampID());
					member->mutable_facade()->CopyFrom(pOffline->GetFacade());
					g_GetCenterService()->SendDataToClient(inviterTeam->Leader(), EMODULE_ID_TEAM, CENTER_TO_CLIENT_APPLY_JOIN_NOTIFY, &notify);
				}
				else
				{
					LogErrFmtPrint("TeamManager::InviteJoinEcho...nullptr == member cid:%lu,inviteId:%lu ", charId, inviteId);
				}
				
				return RET_SUCCESS;
			}
			else
			{
				//将被邀请者加入队伍
				ret = AddToTeam(inviterTeam, charId);
				if (ret == RET_SUCCESS)
				{
					//成功后移除队员自动匹配
					CancelCharacterAutoMatch(charId);
				}
			}

			return ret;
		}
	}
	else
	{
		OfflineCharacterData *pOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
		if (nullptr != pOfflineCharacterData)
		{
			//发送回应结果给邀请者
			ProtoBuf::WCInviteJoinEchoNotify echoNotify;
			echoNotify.set_result(result);
			echoNotify.set_name(pOfflineCharacterData->GetCharName());
			g_GetCenterService()->SendDataToClient(inviteId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_INVITE_JOIN_ECHO_NOTIFY, &echoNotify);

			return RET_SUCCESS;
			
		}
	}

	return RET_SUCCESS;
}

ProtoBuf::ERetCode TeamManager::DeleteMember(CharIDType leaderId, CharIDType deleteId)
{
	Team* myTeam = FindTeam(leaderId);
	if (nullptr == myTeam)
	{
		return RET_TEAM_NO_EXIST;
	}

	if (!myTeam->IsMember(leaderId))
	{
		SetCharcterTeamId(leaderId, INVALID_TEAM_ID);
		return RET_TEAM_NO_EXIST;
	}

	if (!myTeam->IsLeader(leaderId) || deleteId == leaderId)
	{
		return RET_TEAM_NO_AUTHORITY;
	}

	bool success = myTeam->DelMember(deleteId);
	if (success)
	{
		RemoveIndex(deleteId);

		//向所有队员发送剔除玩家通知，包括被踢者
		ProtoBuf::WCDeleteNotify deleteNotify;
		deleteNotify.set_playerid(deleteId);
		deleteNotify.set_leaderid(leaderId);

		//发送离队通知给其它队友
		TeamMember* memberList = myTeam->GetMemberList();
		if (nullptr != memberList)
		{
			uint32_t count = myTeam->MemberCount();
			for (uint32_t i = 0; i != count; ++i)
			{
				g_GetCenterService()->SendDataToClient(memberList[i].playerId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_DELETE_NOTIFY, &deleteNotify);

				//向场景服同步信息
				SendSynTeamNotify(memberList[i].playerId);
			}
		}		

		//deleteNotify.set_playerid(leaderId);
		g_GetCenterService()->SendDataToClient(deleteId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_DELETE_NOTIFY, &deleteNotify);
		SendSynTeamNotify(deleteId);

		return RET_SUCCESS;
	}
	
	return RET_TEAM_NOT_MEMBER;
}

ProtoBuf::ERetCode TeamManager::TransferLeader(CharIDType oldLeaderId, CharIDType newLeaderId)
{
	Team* myTeam = FindTeam(oldLeaderId);
	if (nullptr == myTeam)
	{
		return RET_TEAM_NO_EXIST;
	}

	if (!myTeam->IsMember(oldLeaderId))
	{
		SetCharcterTeamId(oldLeaderId, INVALID_TEAM_ID);
		return RET_TEAM_NO_EXIST;
	}

	if (!myTeam->IsLeader(oldLeaderId) || oldLeaderId == newLeaderId)
	{
		return RET_TEAM_NO_AUTHORITY;
	}

	ActiveCharacter* pLeaderActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(newLeaderId);
	if (nullptr == pLeaderActiveCharacter)
	{
		return RET_PLAYER_NOT_ONLINE;
	}

	//角色离线
	if (myTeam->GetMemberOnline(newLeaderId) == false)
	{
		return RET_PLAYER_NOT_ONLINE;
	}

	ChangeLeader(myTeam, newLeaderId);
	
	return RET_SUCCESS;
}

ProtoBuf::ERetCode TeamManager::TeamSetting(CharIDType charId, uint32_t teamObject, uint32_t minLv, uint32_t maxLv)
{
	const TeamTeamCfgInfo* teamCfgInfo = g_GetTeamTeamCfgTable()->GetTeamTeamCfgInfo(teamObject);
	if (nullptr == teamCfgInfo)
	{
		return RET_TEAM_SETTING_TYPE_ERROR;
	}

	if ((int16_t)minLv < teamCfgInfo->LowLV || (int16_t)maxLv > teamCfgInfo->UpLV)
	{
		return RET_TEAM_SETTING_LV_ERROR;
	}

	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
	{
		return RET_TEAM_NO_EXIST;
	}

	if (!myTeam->IsMember(charId))
	{
		SetCharcterTeamId(charId, INVALID_TEAM_ID);
		return RET_TEAM_NO_EXIST;
	}


	if (!myTeam->IsLeader(charId))
	{
		return RET_TEAM_NO_AUTHORITY;
	}

	uint32_t oldTeamObject = myTeam->GetTeamObjectId();

	myTeam->SetTeamObjectId(teamObject);
	myTeam->SetJoinMinLvLimit((int16_t)minLv);
	myTeam->SetJoinMaxLvLimit((int16_t)maxLv);

	//先移除掉旧的
	if (oldTeamObject != 0 && oldTeamObject != teamObject)
	{
		AutoMatch(charId, oldTeamObject, false);
		//移除掉队伍原先有的旧的队伍类型
		RemoveTeamSetting(oldTeamObject, myTeam);
	}

	//插入队伍新的队伍类型
	InsertTeamSetting(teamObject, myTeam);

	return RET_SUCCESS;
}

ProtoBuf::ERetCode TeamManager::AutoMatch(CharIDType charId, uint32_t teamObject, uint32_t isAutoMatch)
{
	ProtoBuf::ERetCode ret = RET_SUCCESS;
	do 
	{
		Team* myTeam = FindTeam(charId);
		//如果没有队伍
		if (nullptr == myTeam)
		{
			if (isAutoMatch)
			{
				//设置玩家自动匹配
				if (!SetCharacterAutoMatch(charId, teamObject))
				{
					ret = RET_TEAM_HAVE_AUTO_MATCH;
					break;
				}
			}
			else
			{
				//取消自动匹配
				CancelCharacterAutoMatch(charId);
			}
		}
		else
		{
			TeamID_t teamId = myTeam->TeamID();

			//如果不是队长无法进行自动匹配
			if (!myTeam->IsLeader(charId))
			{
				ret = RET_TEAM_NO_AUTHORITY;
			}

			if (isAutoMatch)
			{
				//如果是队长的话 设置的是队伍的自动匹配
				if (!SetTeamAutoMatch(teamId))
				{
					ret = RET_TEAM_HAVE_AUTO_MATCH;
				}
			}
			else
			{
				//如果是队长的话 取消队伍的自动匹配
				CancelTeamAutoMatch(teamId);
			}
		}
		break;
	} while (1);

	ProtoBuf::WCAutoMatchRsp autoMatchRsp;
	autoMatchRsp.set_ret(ret);
	autoMatchRsp.set_isautomatch(isAutoMatch);
	g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_AUTO_MATCH, &autoMatchRsp);

	if (isAutoMatch && ret == RET_SUCCESS)
	{
		std::set<CharIDType> deleteCharacterSet;
		std::map<uint32_t, TeamID_t> deleteTeamSet;
		//进行匹配逻辑处理
		for (TeamAutoMatchCharacterMap::iterator characterIter = _autoMatchCharacterMap.begin(); characterIter != _autoMatchCharacterMap.end(); ++characterIter)
		{
			TeamAutoMatchTeamMap::iterator teamIter = _autoMatchTeamIdMap.find(characterIter->second);
			if (teamIter != _autoMatchTeamIdMap.end())
			{
				for (TeamIdList::iterator idIter = teamIter->second.begin(); idIter != teamIter->second.end(); ++idIter)
				{
					Team* team = FindTeamById(*idIter);
					//如果此时队伍已经不存在了 那么需要移除掉该队伍的自动匹配
					if (nullptr == team)
					{
						deleteTeamSet[characterIter->second] = *idIter;
						//deleteTeamSet.insert(std::make_pair(characterIter->second, *idIter));
					}
					else
					{	
						OfflineCharacterData *pOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(characterIter->first);
						if (nullptr != pOfflineCharacterData)
						{
							//判断一下等级是否符合要求
							if (pOfflineCharacterData->GetLevel() < team->GetJoinMinLvLimit() || pOfflineCharacterData->GetLevel() > team->GetJoinMaxLvLimit())
							{
								continue;
							}

							//加入成功那么需要删除掉匹配中的队员
							if (RET_SUCCESS == AddToTeam(team, characterIter->first))
							{
								deleteCharacterSet.insert(characterIter->first);
							}

							//如果队伍满了删除自动匹配
							if (team->IsFull())
							{
								deleteTeamSet[team->GetTeamObjectId()] = *idIter;
								//deleteTeamSet.insert(std::make_pair(team->GetTeamObjectId(), *idIter));
							}
						}
					}
				}
			}
		}

		//删除掉自动匹配的队伍和队员
		std::set<CharIDType>::iterator deleteCharIter = deleteCharacterSet.begin();
		for (; deleteCharIter != deleteCharacterSet.end(); ++deleteCharIter)
		{
			_autoMatchCharacterMap.erase(*deleteCharIter);
		}

		//删除自动匹配的队伍
		std::map<uint32_t, TeamID_t>::iterator deleteTeamIter = deleteTeamSet.begin();
		for (; deleteTeamIter != deleteTeamSet.end(); ++deleteTeamIter)
		{
			TeamAutoMatchTeamMap::iterator autoMatchiter = _autoMatchTeamIdMap.find(deleteTeamIter->first);
			if (autoMatchiter != _autoMatchTeamIdMap.end())
			{
				autoMatchiter->second.erase(deleteTeamIter->second);
			}
		}
		
	}

	return RET_SUCCESS;
}

ProtoBuf::ERetCode TeamManager::CancelTeam(TeamID_t teamId)
{
	Team* myTeam = FindTeamById(teamId);
	if (nullptr == myTeam)
	{
		return RET_TEAM_NO_EXIST;
	}

	SET_UINT64 memberList;
	myTeam->GetMemeberList(memberList);
	for (auto iter = memberList.begin(); iter != memberList.end(); ++iter)
	{
		RemoveIndex(*iter);
	}

	//移除队伍配置信息
	uint32_t teamObject = myTeam->GetTeamObjectId();
	RemoveTeamSetting(teamObject, myTeam);

	//如果是队伍无效了也要取消队伍的自动匹配
	CancelTeamAutoMatch(myTeam->TeamID());

	//队伍已经没有人,回收队伍
	_teamList.erase(teamId);
	RecoverTeam(myTeam);

	return RET_SUCCESS;
}

ProtoBuf::ERetCode TeamManager::FollowTeam(CharIDType charId)
{
	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
	{
		return RET_TEAM_NO_EXIST;
	}

	if (nullptr != myTeam && myTeam->IsMember(charId) && !myTeam->IsLeader(charId))
	{
		return RET_TEAM_NO_AUTHORITY;
	}

	//队长已经下线了
	ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pActiveCharacter)
	{
		return RET_NOT_ONLINE;
	}

	//队长在副本场景 屏蔽召唤跟随
	uint32_t mapId = pActiveCharacter->GetMapID();
	const MapMapCfgInfo*  pMapCfg = g_GetMapMapCfgTable()->GetMapMapCfgInfo(mapId);
	if (nullptr == pMapCfg || (pMapCfg->mapType == DYNAMIC_MAP && !g_GetMapCfgMgr()->IsUnionDunGeonMap(mapId) && !g_GetMapCfgMgr()->IsUnionHomeMap(mapId)))
	{
		return RET_TEAM_DYNAMIC_MAP_NOT_FOLLOW;
	}

	//设置全队跟随状态
	SET_UINT64 playerList;
	myTeam->GetMemeberList(playerList);
	for (SET_UINT64::iterator iter = playerList.begin(); iter != playerList.end(); ++iter)
	{
		ActiveCharacter *pPlayerActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(*iter);
		if (nullptr == pPlayerActiveCharacter)
		{
			continue;
		}

		if (myTeam->GetMemberOnline(*iter) == false)
		{
			continue;
		}

		if (pPlayerActiveCharacter->GetLifeStatus() == State_dead)
		{
			continue;
		}

		WCTeamEnsureFollowNotify ensureFollowNotify;
		ensureFollowNotify.set_charid(*iter);
		if (myTeam->SceneID() != pPlayerActiveCharacter->GetSceneID())
		{
			myTeam->SetFollow(*iter, false);
			ensureFollowNotify.set_isfollow(false);
			ensureFollowNotify.set_issamescene(false);
		}
		else
		{
			myTeam->SetFollow(*iter, true);
			ensureFollowNotify.set_isfollow(true);
			ensureFollowNotify.set_issamescene(true);
		}

		for (SET_UINT64::iterator tIter = playerList.begin(); tIter != playerList.end(); ++tIter)
		{
			if (myTeam->GetMemberOnline(*tIter) == false)
			{
				continue;
			}

			ActiveCharacter *pTActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(*tIter);
			if (nullptr == pTActiveCharacter)
			{
				continue;
			}

			if (pTActiveCharacter->GetLifeStatus() == State_dead)
			{
				continue;
			}

			//只给同一个场景的队员设置跟随状态
			//ensureFollowNotify.set_charid(*tIter);
			//g_GetCenterService()->SendDataToClient(*iter, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_ENSURE_FOLLOW_NOTIFY, &ensureFollowNotify);
			g_GetCenterService()->SendDataToClient(*tIter, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_ENSURE_FOLLOW_NOTIFY, &ensureFollowNotify);
		}
		//通知非跟随状态的成员
		//BroadcastTeam(*iter, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_ENSURE_FOLLOW_NOTIFY, &ensureFollowNotify, true);
	}

/*	ProtoBuf::WCMemberStatusNotify notify;
	notify.set_playerid(charId);
	notify.set_status(EPGST_TYPE_FOLLOW);

	BroadcastTeam(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_MEMBER_LOGOFF_NOTIFY, &notify)*/;

	return RET_SUCCESS;
}

ProtoBuf::ERetCode TeamManager::CallFollowTeam(CharIDType charId)
{
	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
	{
		return RET_TEAM_NO_EXIST;
	}

	if (!myTeam->IsLeader(charId))
	{
		return RET_TEAM_NOT_LEADER;
	}

	ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	if (nullptr == pActiveCharacter)
	{
		return RET_NOT_ONLINE;
	}

	//队长在副本场景 屏蔽召唤跟随
	uint32_t mapId = pActiveCharacter->GetMapID();
	const MapMapCfgInfo* pMapCfg = g_GetMapMapCfgTable()->GetMapMapCfgInfo(mapId);
	if (nullptr == pMapCfg || (pMapCfg->mapType == DYNAMIC_MAP && !g_GetMapCfgMgr()->IsUnionDunGeonMap(mapId) && !g_GetMapCfgMgr()->IsUnionHomeMap(mapId)))
	{
		return RET_TEAM_DYNAMIC_MAP_NOT_FOLLOW;
	}

	//队长通知其他队员
	ProtoBuf::WCTeamFollowNotify teamFollowNotify;
	teamFollowNotify.set_leaderid(charId);

	SET_UINT64 playerList;
	myTeam->GetMemeberList(playerList);
	for (SET_UINT64::iterator iter = playerList.begin(); iter != playerList.end(); ++iter)
	{
		CharIDType memberCid = *iter;
		if (memberCid == charId)
		{
			continue;
		}

		ActiveCharacter *pPlayerActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(memberCid);
		if (nullptr == pPlayerActiveCharacter)
		{
			continue;
		}

		if (myTeam->GetMemberOnline(memberCid) == false)
		{
			continue;
		}

		if (pPlayerActiveCharacter->GetLifeStatus() == State_dead)
		{
			continue;
		}
		g_GetCenterService()->SendDataToClient(memberCid, EMODULE_ID_TEAM, CENTER_TO_CLIENT_TEAM_FOLLOW_NOTIFY, &teamFollowNotify);
	}

	return RET_SUCCESS;
}

//ProtoBuf::ERetCode TeamManager::EnsureFollowTeam(CharIDType charId, bool isFollow)
//{
//	Team* myTeam = FindTeam(charId);
//	if (nullptr == myTeam)
//	{
//		return RET_TEAM_NO_EXIST;
//	}
//
//	if (nullptr != myTeam && !myTeam->IsMember(charId))
//	{
//		return RET_TEAM_NO_EXIST;
//	}
//
//	if (myTeam->IsLeader(charId))
//	{
//		return RET_FAIL;
//	}
//
//	ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
//	if (nullptr == pActiveCharacter)
//	{
//		return RET_NOT_ONLINE;
//	}
//
//	myTeam->SetFollow(charId, isFollow);
//
//	//ProtoBuf::WCMemberStatusNotify notify;
//	//notify.set_playerid(charId);
//	//if (isFollow)
//	//{
//	//	notify.set_status(EPGST_TYPE_FOLLOW);
//	//}
//	//else
//	//{
//	//	notify.set_status(EPGST_TYPE_CANCEL_FOLLOW);
//	//}
//
//	//BroadcastTeam(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_MEMBER_LOGOFF_NOTIFY, &notify);
//
//	return RET_SUCCESS;
//}

ProtoBuf::ERetCode TeamManager::CancelFollowTeam(CharIDType charId)
{
	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
	{
		return RET_TEAM_NO_EXIST;
	}

	if (nullptr != myTeam && !myTeam->IsMember(charId))
	{
		return RET_TEAM_NO_EXIST;
	}

	if (!myTeam->IsLeader(charId))
	{
		return RET_TEAM_NOT_LEADER;
	}

	//取消队伍所有人的跟随状态
	myTeam->CancelAllFollow();

	return RET_SUCCESS;
}

Team* TeamManager::CreateTeamEx()
{
	Team* team = nullptr;
	FreeTeamList::iterator iter = _freeTeamList.begin();
	while (_freeTeamList.end() != iter)
	{
		team = *iter;
		_freeTeamList.erase(iter);
		if (nullptr == team)
		{
			iter = _freeTeamList.begin();
		}
		else
		{
			team->CleanUp();
			return team;
		}
	}

	team = _teamPool->MallocObj();
	return team;
}

TeamID_t TeamManager::CreateTeamId()
{
	uint32_t id = 0;
	int count = 0;
	do {
		id = _team_id++;
		if (id == 0){
			id = _team_id++;
		}
	} while (_teamList.count(id) > 0 && count++ < 20);

	return id;
}

Team* TeamManager::FindTeam(CharIDType charId)
{
	TeamID_t teamId = GetTeamId(charId);

	return FindTeamById(teamId);
}

Team* TeamManager::FindTeamById(TeamID_t teamId)
{
	TeamList::iterator iter = _teamList.find(teamId);
	if (iter != _teamList.end())
	{
		return iter->second;
	}

	return nullptr;
}

TeamID_t TeamManager::GetTeamId(CharIDType charId)
{
	TeamIdMap::iterator iter = _teamIdMap.find(charId);
	if (iter != _teamIdMap.end())
	{
		return iter->second;
	}

	return 0;
}

void TeamManager::SetCharcterTeamId(const CharIDType& charId, const TeamID_t& teamId)
{
	_teamIdMap[charId] = teamId;
	//_teamIdMap.insert(std::make_pair(charId, teamId));
}

bool TeamManager::CheckCreateLevel(const uint32_t& level)
{
	if (level >= TEAM_MIN_LEVEL)
	{
		return true;
	}

	return false;
}

bool TeamManager::CheckInJail(uint32_t sceneId)
{
	return sceneId == _const_jail_id;
}

void TeamManager::RecoverTeam(Team* team)
{
	if (nullptr != team)
	{
		MMOLOG_FMT_DEBUG("[logic] RecoverTeam team=%u", team->TeamID());
		this->RemoveFromScene(team->SceneID(), team->TeamID());
		team->CleanUp();
		_freeTeamList.insert(team);
	}
}

void TeamManager::RemoveFromScene(const uint32_t& sceneId, const TeamID_t& teamId)
{
	SceneTeamList::iterator iter = _sceneTeamList.find(sceneId);
	if (_sceneTeamList.end() != iter)
	{
		iter->second.erase(teamId);
	}
}

void TeamManager::AddIndex(const CharIDType& charId, const TeamID_t& teamId)
{
	_teamIdMap[charId] = teamId;
	//_teamIdMap.insert(std::make_pair(charId, teamId));
}

void TeamManager::RemoveIndex(const CharIDType& charId)
{
	_teamIdMap.erase(charId);
}

void TeamManager::AddToScene(const uint32_t& sceneId, const TeamID_t& teamId)
{
	SceneTeamList::iterator iter = _sceneTeamList.find(sceneId);
	if (_sceneTeamList.end() != iter)
	{
		iter->second.insert(teamId);
	}
	else
	{
		TeamIdList list;
		list.insert(teamId);
		_sceneTeamList[sceneId] = list;
	//	_sceneTeamList.insert(std::make_pair(sceneId, list));
	}
}

void TeamManager::GetTeamInfo(ActiveCharacter* pActiveCharacter, ProtoBuf::TeamInfo& info)
{
	if (nullptr == pActiveCharacter)
	{
		return;
	}

	CharIDType charId = pActiveCharacter->GetCharID();
	uint32_t sceneId = pActiveCharacter->GetSceneID();
	Team* myTeam = FindTeam(charId);
	if (NULL == myTeam || !myTeam->IsMember(charId))
	{
		info.set_id(INVALID_TEAM_ID);
		info.set_isauto(IsTeamAutoMatch(charId));
	}
	else
	{
		info.set_id(myTeam->TeamID());
		info.set_leaderid(myTeam->Leader());
		info.set_sceneid(sceneId);
		info.set_isauto(IsTeamAutoMatch(myTeam->Leader()));
		info.set_teamobject(myTeam->GetTeamObjectId());
		info.set_minlv(myTeam->GetJoinMinLvLimit());
		info.set_maxlv(myTeam->GetJoinMaxLvLimit());

		uint32_t count = myTeam->MemberCount();
		TeamMember* list = myTeam->GetMemberList();
		if (nullptr != list)
		{
			for (uint32_t i = 0; i != count; ++i)
			{
				OfflineCharacterData *pOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(list[i].playerId);
				if (nullptr == pOfflineCharacterData)
				{
					continue;
				}

				ProtoBuf::TeamMemberInfo* member = info.add_memberlist();
				member->set_playerid(list[i].playerId);
				member->set_name(pOfflineCharacterData->GetCharName());
				member->set_level(pOfflineCharacterData->GetLevel());
				member->set_profession(pOfflineCharacterData->GetProf());
				member->set_sex(pOfflineCharacterData->GetSex());
				member->set_sceneid(list[i].sceneId);
				member->mutable_facade()->CopyFrom(pOfflineCharacterData->GetFacade());
				member->set_isfollow(list[i].isFollow);
				member->set_jointime(list[i].joinTime);
				member->set_fightpower(pOfflineCharacterData->GetFight());
				member->set_campid(pOfflineCharacterData->GetCampID());

				ActiveCharacter* pOnlineCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(list[i].playerId);
				if (nullptr != pOnlineCharacter)
				{
					member->set_online(true);
				}
			}
		}		
	}
}

void TeamManager::SendSynTeamNotify(const CharIDType& charId)
{
	Team* myTeam = FindTeam(charId);
	ProtoBuf::WGUpdateTeamNotify notify;
	uint32_t closenessLv = 0;
	if (nullptr != myTeam && myTeam->IsMember(charId))
	{
		notify.set_teamid(myTeam->TeamID());
		notify.set_isleader(myTeam->IsLeader(charId));
		//这里需要同步一下自己跟其他队员的亲密度最大等级
		closenessLv = myTeam->GetTeamClosenessLv(charId);
	}
	else
	{
		notify.set_teamid(0);
		notify.set_isleader(0);
	}

	notify.set_charid(charId);
	notify.set_closenesslv(closenessLv);
	g_GetCenterService()->SendDataToLogicByCharID(charId, EMODULE_ID_TEAM, CENTER_TO_LOGIC_UPDATE_TEAM_NOTIFY, &notify);
}

void TeamManager::LoginSyncData(CharIDType charId, CharLoginSyncCenterData *protoLoginSync)
{
	Team* myTeam = FindTeam(charId);
	if (nullptr != myTeam && myTeam->IsMember(charId))
	{
		protoLoginSync->set_team_id(myTeam->TeamID());
		protoLoginSync->set_is_leader(myTeam->IsLeader(charId));
	}
	else
	{
		protoLoginSync->set_team_id(0);
		protoLoginSync->set_is_leader(0);
	}
	//切逻辑节点发亲密度到逻辑服计算属性加成
	//SendSynTeamNotify(charId);
}

void TeamManager::AddTeamCloseness(CharIDType charId, uint32_t type)
{
	//通知全队的人并且是好友关系的人互相加亲密值
	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
	{
		return;
	}

	//给全队的人加亲密度值
	myTeam->AddTeamCloseness(type);

	//通知全队各自的人亲密度等级发生改变
	WGTeamClonsenessLvNotify notify;
	uint32_t count = myTeam->MemberCount();
	TeamMember* list = myTeam->GetMemberList();
	if (nullptr != list)
	{
		for (uint32_t i = 0; i != count; ++i)
		{
			//获取自己跟全队中其他好友关系的最大亲密度等级
			uint32_t closenessLv = myTeam->GetTeamClosenessLv(list[i].playerId);
			notify.set_charid(list[i].playerId);
			notify.set_closenesslv(closenessLv);
			g_GetCenterService()->SendDataToLogicByCharID(list[i].playerId, EMODULE_ID_TEAM, CENTER_TO_LOGIC_CLOSENESS_LEVEL_NOTIFY, &notify);
		}
	}	
}

void TeamManager::TeamClosenessUpdate(CharIDType charId)
{
	//通知全队的人并且是好友关系的人亲密值
	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
	{
		return;
	}
	WGTeamClonsenessLvNotify notify;
	uint32_t count = myTeam->MemberCount();
	TeamMember* list = myTeam->GetMemberList();
	if (nullptr != list)
	{
		for (uint32_t i = 0; i != count; ++i)
		{
			//获取自己跟全队中其他好友关系的最大亲密度等级
			uint32_t closenessLv = myTeam->GetTeamClosenessLv(list[i].playerId);
			notify.set_charid(list[i].playerId);
			notify.set_closenesslv(closenessLv);
			g_GetCenterService()->SendDataToLogicByCharID(list[i].playerId, EMODULE_ID_TEAM, CENTER_TO_LOGIC_CLOSENESS_LEVEL_NOTIFY, &notify);
		}
	}
}

void TeamManager::DuplicatePass(CharIDType charId)
{
	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
	{
		return;
	}

	if (!myTeam->IsLeader(charId))
	{
		return;
	}

	//通知队长加亲密度就可以了 队长会一起帮其他队员累加亲密度了
	AddTeamCloseness(charId, RELATION_CLOSENESS_PASS_DUP);
}

void TeamManager::AddRelationInTeam(CharIDType agreeID, CharIDType applyID)
{
	Team* myTeam = FindTeam(agreeID);
	if (nullptr == myTeam)
	{
		return;
	}
	if (!myTeam->IsMember(applyID))
	{
		return;
	}
	myTeam->AddTeamCloseness(RELATION_CLOSENESS_JOIN_TEAM);
	TeamMember* memberList = myTeam->GetMemberList();
	if (nullptr != memberList)
	{
		uint32_t count = myTeam->MemberCount();
		for (uint32_t i = 0; i != count; ++i)
		{
			//向场景服同步信息
			SendSynTeamNotify(memberList[i].playerId);
		}
	}
}

ProtoBuf::ERetCode TeamManager::AddToTeam(Team* team, const CharIDType& dstId)
{
	if (nullptr == team)
	{
		return RET_TEAM_NO_EXIST;
	}

	ActiveCharacter* pActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(dstId);
	if (nullptr == pActiveCharacter)
	{
		return RET_PLAYER_NOT_ONLINE;
	}

	OfflineCharacterData *pOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(dstId);
	if (nullptr == pOfflineCharacterData)
	{
		return RET_NOT_HAVE_CHARACTER;
	}

	Team* myTeam = FindTeam(dstId);
	if (nullptr != myTeam)
	{
		return RET_TEAM_REPEAT_JOIN;
	}

	if (team->IsFull())
	{
		return RET_TEAM_FULL;
	}

	if (team->IsMember(dstId))
	{
		team->SetFollow(dstId, false);
		SetCharcterTeamId(dstId, team->TeamID());
		return RET_TEAM_REPEAT_JOIN;
	}

	TeamMember* member = nullptr;
	if (!team->AddMember(dstId, member))
	{
		return RET_TEAM_FULL;
	}
	
	uint32_t sceneId = pActiveCharacter->GetSceneID();
	member->identity = IDENTITY_MEMBER;
	member->sceneId = sceneId;

	AddIndex(dstId, team->TeamID());
	team->AddTeamCloseness(RELATION_CLOSENESS_JOIN_TEAM);
	TeamMember* memberList = team->GetMemberList();
	if (nullptr != memberList)
	{
		uint32_t count = team->MemberCount();
		for (uint32_t i = 0; i != count; ++i)
		{
			//向场景服同步信息
			SendSynTeamNotify(memberList[i].playerId);

			//把有新队员加入广播给同场景队友
			if (memberList[i].playerId == dstId)
			{
				//自己
				continue;
			}

			ProtoBuf::WCJoinTeamNotify notify;
			ProtoBuf::TeamMemberInfo* memberInfo = notify.add_joinlist();

			memberInfo->set_playerid(dstId);
			memberInfo->set_name(pOfflineCharacterData->GetCharName());
			memberInfo->set_level(pOfflineCharacterData->GetLevel());
			memberInfo->set_profession(pOfflineCharacterData->GetProf());
			memberInfo->set_sceneid(sceneId);
			memberInfo->set_sex(pOfflineCharacterData->GetSex());
			memberInfo->mutable_facade()->CopyFrom(pOfflineCharacterData->GetFacade());
			memberInfo->set_jointime(memberList[i].joinTime);
			memberInfo->set_fightpower(pOfflineCharacterData->GetFight());
			memberInfo->set_campid(pOfflineCharacterData->GetCampID());

			//发送通知给其它队友
			g_GetCenterService()->SendDataToClient(memberList[i].playerId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_JOIN_TEAM_NOTIFY, &notify);
		}

		//向自己发送更新组队信息通知
		ProtoBuf::WCUpdateTeamInfoNotify notify;
		//自己队伍信息
		GetTeamInfo(pActiveCharacter, *(notify.mutable_teaminfo()));
		g_GetCenterService()->SendDataToClient(dstId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_UPDATE_TEAM_INFO_NOTIFY, &notify);

		//将别人加进自己的临时列表
		for (uint32_t i = 0; i != count; ++i)
		{
			if (memberList[i].playerId == dstId)
			{
				continue;
			}

			g_GetRelationMgr()->UpdateRecentList(memberList[i].playerId, dstId, RELATION_RECENT_TEAM);
		}
	}	

	//删除申请列表
	if (team->HaveApplicant(dstId))
	{
		team->DelApplicant(dstId);
		WCDeleteApplyMember deleteApply;
		deleteApply.set_charid(dstId);
		g_GetCenterService()->SendDataToClient(team->Leader(), EMODULE_ID_TEAM, CENTER_TO_CLIENT_DELETE_APPLAY, &deleteApply);
	}
	
	return RET_SUCCESS;
}

void TeamManager::SendJoinTeamEchoNotify(const CharIDType& leaderId, const std::vector<CharIDType>& disagreeList)
{
	OfflineCharacterData *pOfflineCharacterData = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(leaderId);
	if (nullptr == pOfflineCharacterData)
	{
		return;
	}

	ProtoBuf::WCJoinTeamEchoNotify notify;
	notify.set_name(pOfflineCharacterData->GetCharName());
	for (uint32_t i = 0; i < disagreeList.size(); i++)
	{
		g_GetCenterService()->SendDataToClient(disagreeList[i], EMODULE_ID_TEAM, CENTER_TO_CLIENT_JOIN_TREA_ECHO_NOTIFY, &notify);
	}
}

void TeamManager::ChangeLeader(Team* team, const CharIDType& newLeaderId)
{
	if (NULL != team && RET_SUCCESS == team->TransferLeader(newLeaderId))
	{
		//转让成功后取消队伍的自动匹配设置
		CancelTeamAutoMatch(team->TeamID());

		//转让队长要清空原来的申请列表
		team->ClearApplicant();

		//转让队长的话取消全队的跟随状态
		team->CancelAllFollow();
		ProtoBuf::WCCancelFollowNotify cancelFollowNotify;
		cancelFollowNotify.set_leaderid(newLeaderId);
		BroadcastTeam(newLeaderId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_CANCEL_FOLLOW_NOTIFY, &cancelFollowNotify);

		ActiveCharacter* pLeaderActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(newLeaderId);
		if (nullptr != pLeaderActiveCharacter)
		{
			//需要将队伍的场景设置为该队长对应的场景ID
			TeamMember* member = team->GetMember(newLeaderId);
			if (nullptr != member)
			{
				RemoveFromScene(team->SceneID(), team->TeamID());
				AddToScene(member->sceneId, team->TeamID());
				team->SetSceneID(member->sceneId);
			}
		}

		//发送更换队长通知给所有队员
		ProtoBuf::WCChangeLeaderNotify msg;
		msg.set_leaderid(team->Leader());
		
		TeamMember* memberList = team->GetMemberList();
		uint32_t count = team->MemberCount();
		if (nullptr != memberList)
		{
			for (uint32_t i = 0; i != count; ++i)
			{
				//向场景服同步信息
				SendSynTeamNotify(memberList[i].playerId);
			}

			//通知队员
			for (uint32_t i = 0; i < count; i++)
			{
				g_GetCenterService()->SendDataToClient(memberList[i].playerId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_CHANGE_LEADER_NOTIFY, &msg);
			}
		}		
	}
}

bool TeamManager::SetTeamAutoMatch(const TeamID_t& teamId)
{
	Team* myTeam = FindTeamById(teamId);
	if (nullptr == myTeam)
	{
		return false;
	}

	//if (!myTeam->isLeader(charId))
	//{
	//	return false;
	//}

	TeamAutoMatchTeamMap::iterator iter = _autoMatchTeamIdMap.find(myTeam->GetTeamObjectId());
	if (iter != _autoMatchTeamIdMap.end())
	{
		TeamIdList::iterator teamIter = iter->second.find(myTeam->TeamID());
		if (teamIter != iter->second.end())
		{
			return false;
		}
		else
		{
			iter->second.insert(myTeam->TeamID());
		}
	}
	else
	{
		TeamIdList teamIds;
		teamIds.insert(myTeam->TeamID());
		_autoMatchTeamIdMap[myTeam->GetTeamObjectId()] = teamIds;
		//_autoMatchTeamIdMap.insert(std::make_pair(myTeam->GetTeamObjectId(), teamIds));
	}
	
	return true;
}

bool TeamManager::SetCharacterAutoMatch(const CharIDType& charId, const uint32_t& teamObject)
{
	//如果没有队伍的 那么是请求来自动匹配的玩家
	TeamAutoMatchCharacterMap::iterator iter = _autoMatchCharacterMap.find(charId);
	if (iter != _autoMatchCharacterMap.end())
	{
		return false;
	}

	_autoMatchCharacterMap[charId] = teamObject;
	//_autoMatchCharacterMap.insert(std::make_pair(charId, teamObject));

	return true;
}

bool TeamManager::IsTeamAutoMatch(const CharIDType& charId)
{
	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
	{
		return false;
	}

	TeamAutoMatchTeamMap::iterator iter = _autoMatchTeamIdMap.find(myTeam->GetTeamObjectId());
	if (iter != _autoMatchTeamIdMap.end())
	{
		TeamIdList::iterator teamIter = iter->second.find(myTeam->TeamID());
		if (teamIter == iter->second.end())
		{
			return false;
		}
		else
		{
			return true;
		}
	}

	return false;
}

bool TeamManager::CancelCharacterAutoMatch(const CharIDType& charId)
{
	TeamAutoMatchCharacterMap::iterator iter = _autoMatchCharacterMap.find(charId);
	if (iter != _autoMatchCharacterMap.end())
	{
		_autoMatchCharacterMap.erase(charId);
		return true;
	}

	return false;
}

bool TeamManager::CancelTeamAutoMatch(const TeamID_t& teamId)
{
	Team* myTeam = FindTeamById(teamId);
	if (nullptr == myTeam)
	{
		return false;
	}

	//if (!myTeam->isLeader(charId))
	//{
	//	return false;
	//}

	TeamAutoMatchTeamMap::iterator iter = _autoMatchTeamIdMap.find(myTeam->GetTeamObjectId());
	if (iter != _autoMatchTeamIdMap.end())
	{
		TeamIdList::iterator teamIter = iter->second.find(myTeam->TeamID());
		if (teamIter != iter->second.end())
		{
			iter->second.erase(myTeam->TeamID());
			return true;
		}
	}

	return false;
}

void TeamManager::BroadcastTeam(CharIDType charId, uint16_t module, uint16_t cmd, ProtoBufBase* msg, bool notFollow, bool isExcept)
{
	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
	{
		return;
	}

	SET_UINT64 playerList;
	if (notFollow)
	{
		myTeam->GetNotFollowMemberList(playerList);
	}
	else
	{
		myTeam->GetMemeberList(playerList);
	}
	
	if (isExcept)
	{
		playerList.erase(charId);
	}

	if (playerList.size() > 0)
	{
		g_GetCenterService()->SendDataToClient(playerList, module, cmd, msg);
	}
}

void TeamManager::RemoveTeamSetting(const uint32_t& teamObject, Team* team)
{
	TeamObjectMap::iterator iter = _teamTypeIdMap.find(teamObject);
	if (iter != _teamTypeIdMap.end())
	{
		iter->second.erase(team);
	}
}

void TeamManager::InsertTeamSetting(const uint32_t& teamObject, Team* team)
{
	TeamObjectMap::iterator iter = _teamTypeIdMap.find(teamObject);
	if (iter == _teamTypeIdMap.end())
	{
		TeamSet teamSet;
		teamSet.insert(team);
		_teamTypeIdMap[teamObject] = teamSet;
		//_teamTypeIdMap.insert(std::make_pair(teamObject, teamSet));
	}
	else
	{
		iter->second.insert(team);
	}
}

void TeamManager::OnLogin(ActiveCharacter *pOnlineCharacter)
{
	CharIDType charId = pOnlineCharacter->GetCharID();
	Team* myTeam = FindTeam(charId);
	if (nullptr != myTeam)
	{
		//设置在线标识
		myTeam->SetMemberOnline(charId, pOnlineCharacter->GetSceneID());

		//离线通知
		ProtoBuf::WCMemberStatusNotify notify;
		notify.set_playerid(charId);
		notify.set_status(EPGST_TYPE_LOGIN);

		BroadcastTeam(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_MEMBER_LOGOFF_NOTIFY, &notify, false, false);
		//uint32_t count = myTeam->MemberCount();
		//TeamMember* memberList = myTeam->GetMemberList();
		//for (uint32_t i = 0; i != count; ++i)
		//{
		//	if (memberList[i].playerId != charId)
		//	{
		//		g_GetCenterService()->SendDataToClient(memberList[i].playerId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_MEMBER_LOGOFF_NOTIFY, &notify);
		//	}
		//}
	}
	SendSynTeamNotify(charId);
}

void TeamManager::OnLogoff(ActiveCharacter *pOnlineCharacter)
{
	//队员掉线了
	//如果是队长掉线了 那么需要做队长转让操作 并且需要取消掉自动匹配规则
	//如果队长是队伍中的最后一个人或者是全部人离线了那么解散队伍

	CharIDType charId = pOnlineCharacter->GetCharID();
	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
	{
		//如果是没有队伍的话 移除该玩家的自动匹配设置
		CancelCharacterAutoMatch(charId);
		return;
	}

	if (!myTeam->IsMember(charId))
	{
		//如果是没有队伍的话 移除该玩家的自动匹配设置
		SetCharcterTeamId(charId, INVALID_TEAM_ID);
		CancelCharacterAutoMatch(charId);
		return;
	}

	//设置改队员离线了
	myTeam->SetMemberOffline(charId);

	//检测该队伍是否有效
	if (!myTeam->IsValid())
	{
		//无效解散队伍
		CancelTeam(myTeam->TeamID());
	}
	else
	{
		//离线通知
		ProtoBuf::WCMemberStatusNotify notify;
		notify.set_playerid(charId);
		notify.set_status(EPGST_TYPE_OFFLINE);

		bool isLeader = myTeam->IsLeader(charId);
		if (isLeader)
		{
			CharIDType newLeader = myTeam->ChangeLeader();
			if (newLeader == 0) //这里再做一次容错 如果没有新上人的队长那么直接解散了队伍
			{
				CancelTeam(myTeam->TeamID());
				return;
			}
			else
			{
				ChangeLeader(myTeam, newLeader);
			}
		}
		else
		{
			//取消该队员的跟随状态
			myTeam->SetFollow(charId, false);
		}
		BroadcastTeam(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_MEMBER_LOGOFF_NOTIFY, &notify, false, true);
	}
}

void TeamManager::OnHpUpdate(ActiveCharacter *pOnlineCharacter)
{
	CharIDType charId = pOnlineCharacter->GetCharID();
	if (charId > 0)
	{
		int32_t Hp = pOnlineCharacter->GetLastAttrUpdate(C_HP);
		int32_t MaxHp = pOnlineCharacter->GetLastAttrUpdate(C_MAX_HP);
		int32_t Level = pOnlineCharacter->GetLastAttrUpdate(C_LEVEL);

		if (Hp < 0 && Level < 0 && MaxHp < 0)
		{
			return;
		}

		WCMemberAttrUpdateToMeNotify notifys;
		WCMemberHpUpdateNotify* notify = notifys.add_notifys();
		notify->set_memberid(charId);
		if (Hp >= 0)
		{
			//死亡取消跟随
			if (Hp == 0)
			{
				Team* myTeam = FindTeam(charId);
				if (nullptr != myTeam && myTeam->IsMember(charId))
				{
					//如果是队长的话取消所有跟随状态
					if (myTeam->IsLeader(charId))
					{
						myTeam->CancelAllFollow();
					}
					//普通队员
					else
					{
						//取消该队员的跟随状态
						myTeam->SetFollow(charId, false);
					}
				}
			}

			Attr* attr = notify->add_attrchange();
			attr->set_attrnum(P_HP);
			attr->set_attrvalue(Hp);
		}

		if (MaxHp >= 0)
		{
			Attr* attr = notify->add_attrchange();
			attr->set_attrnum(P_MAX_HP);
			attr->set_attrvalue(MaxHp);
		}

		if (Level >= 0)
		{
			Attr* attr = notify->add_attrchange();
			attr->set_attrnum(P_LEVEL);
			attr->set_attrvalue(Level);
		}

		BroadcastTeam(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_OTHERMEMBERHPUPDATETOMENOTIFY, &notifys);
	}
}

void TeamManager::OnOtherHpUpdate(CharIDType charId)
{
	ActiveCharacter* pOnlineCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(charId);
	//CharIDType charId = pOnlineCharacter->GetCharID();
	if (charId > 0)
	{
		Team* myTeam = FindTeam(charId);
		if (nullptr == myTeam)
		{
			return;
		}

		SET_UINT64 playerList;
		myTeam->GetMemeberList(playerList);
		WCMemberAttrUpdateToMeNotify notifys;
		SET_UINT64::iterator iter = playerList.begin();
		for (; iter != playerList.end(); iter++)
		{
			if (charId == *iter)
			{
				continue;
			}

			ActiveCharacter* pOtherActiveCharacter = g_GetActiveCharacterMgr()->GetOnlineCharacter(*iter);
			if (nullptr != pOtherActiveCharacter)
			{

				int32_t Hp = pOnlineCharacter->GetLastAttrUpdate(C_HP);
				int32_t Level = pOnlineCharacter->GetLastAttrUpdate(C_LEVEL);
				int32_t MaxHp = pOnlineCharacter->GetLastAttrUpdate(C_MAX_HP);

				if (Hp < 0 && Level < 0 && MaxHp < 0)
				{
					return;
				}

				WCMemberHpUpdateNotify* notify = notifys.add_notifys();
				notify->set_memberid(*iter);
				if (Hp >= 0)
				{
					Attr* attr = notify->add_attrchange();
					attr->set_attrnum(P_HP);
					attr->set_attrvalue(Hp);
				}

				if (MaxHp >= 0)
				{
					Attr* attr = notify->add_attrchange();
					attr->set_attrnum(P_MAX_HP);
					attr->set_attrvalue(MaxHp);
				}

				if (Level >= 0)
				{
					Attr* attr = notify->add_attrchange();
					attr->set_attrnum(P_LEVEL);
					attr->set_attrvalue(Level);
				}
			}
		}

		if (playerList.size() - 1 > 0)
		{
			g_GetCenterService()->SendDataToClient(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_OTHERMEMBERHPUPDATETOMENOTIFY, &notifys);
		}
	}
}

void TeamManager::OnDeleteCharacter(OfflineCharacterData* pOnlineCharacter)
{
	//删除队员
	//如果是队长掉线了 那么需要做队长转让操作 并且需要取消掉自动匹配规则
	//如果队长是队伍中的最后一个人或者是全部人离线了那么解散队伍

	CharIDType charId = pOnlineCharacter->GetCharID();
	Team* myTeam = FindTeam(charId);
	if (nullptr == myTeam)
	{
		//如果是没有队伍的话 移除该玩家的自动匹配设置
		CancelCharacterAutoMatch(charId);
		//如果该角色在其他队伍的申请列表中 即时删除
		for (TeamList::iterator iter = _teamList.begin(); iter != _teamList.end(); ++iter)
		{
			if (nullptr == iter->second)	continue;
			if (iter->second->HaveApplicant(charId))
			{
				iter->second->DelApplicant(charId);
				WCDeleteApplyMember deleteApply;
				deleteApply.set_charid(charId);
				g_GetCenterService()->SendDataToClient(iter->second->Leader(), EMODULE_ID_TEAM, CENTER_TO_CLIENT_DELETE_APPLAY, &deleteApply);
			}
		}
		return;
	}

	if (!myTeam->IsMember(charId))
	{
		//如果是没有队伍的话 移除该玩家的自动匹配设置
		SetCharcterTeamId(charId, INVALID_TEAM_ID);
		CancelCharacterAutoMatch(charId);
		return;
	}

	//设置改队员离线了
	myTeam->SetMemberOffline(charId);

	//检测该队伍是否有效
	if (!myTeam->IsValid())
	{
		//无效解散队伍
		CancelTeam(myTeam->TeamID());
	}
	else
	{
		//通知其他成员有人退出了
		ProtoBuf::WCMemberQuitNotify msg;
		msg.set_playerid(charId);
		BroadcastTeam(charId, EMODULE_ID_TEAM, CENTER_TO_CLIENT_MEMBER_QUIT_NOTIFY, &msg, false, true);

		bool isLeader = myTeam->IsLeader(charId);
		//如果是要删除该成员的
		//移除队员
		myTeam->DelMember(charId);
		RemoveIndex(charId);

		if (isLeader)
		{
			CharIDType newLeader = myTeam->ChangeLeader();
			if (newLeader == 0) //这里再做一次容错 如果没有新上人的队长那么直接解散了队伍
			{
				CancelTeam(myTeam->TeamID());
			}
			else
			{
				ChangeLeader(myTeam, newLeader);
			}
		}
	}
}
